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'.
-//===-- BuiltinTypeNodes.def - Metadata about BuiltinTypes ------*- C++ -*-===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This file defines the database about various builtin singleton types.\r
-//\r
-// BuiltinType::Id is the enumerator defining the type.\r
-//\r
-// Context.SingletonId is the global singleton of this type. Some global\r
-// singletons are shared by multiple types.\r
-//\r
-// BUILTIN_TYPE(Id, SingletonId) - A builtin type that has not been\r
-// covered by any other #define. Defining this macro covers all\r
-// the builtins.\r
-//\r
-// SIGNED_TYPE(Id, SingletonId) - A signed integral type.\r
-//\r
-// UNSIGNED_TYPE(Id, SingletonId) - An unsigned integral type.\r
-//\r
-// FLOATING_TYPE(Id, SingletonId) - A floating-point type.\r
-//\r
-// PLACEHOLDER_TYPE(Id, SingletonId) - A placeholder type. Placeholder\r
-// types are used to perform context-sensitive checking of specific\r
-// forms of expression.\r
-//\r
-// SHARED_SINGLETON_TYPE(Expansion) - The given expansion corresponds\r
-// to a builtin which uses a shared singleton type.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#ifndef SIGNED_TYPE\r
-#define SIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)\r
-#endif\r
-\r
-#ifndef UNSIGNED_TYPE\r
-#define UNSIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)\r
-#endif\r
-\r
-#ifndef FLOATING_TYPE\r
-#define FLOATING_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)\r
-#endif\r
-\r
-#ifndef PLACEHOLDER_TYPE\r
-#define PLACEHOLDER_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)\r
-#endif\r
-\r
-#ifndef SHARED_SINGLETON_TYPE\r
-#define SHARED_SINGLETON_TYPE(Expansion) Expansion\r
-#endif\r
-\r
-//===- Builtin Types ------------------------------------------------------===//\r
-\r
-// void\r
-BUILTIN_TYPE(Void, VoidTy)\r
-\r
-//===- Unsigned Types -----------------------------------------------------===//\r
-\r
-// 'bool' in C++, '_Bool' in C99\r
-UNSIGNED_TYPE(Bool, BoolTy)\r
-\r
-// 'char' for targets where it's unsigned\r
-SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(Char_U, CharTy))\r
-\r
-// 'unsigned char', explicitly qualified\r
-UNSIGNED_TYPE(UChar, UnsignedCharTy)\r
-\r
-// 'wchar_t' for targets where it's unsigned\r
-SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(WChar_U, WCharTy))\r
-\r
-// 'char16_t' in C++\r
-UNSIGNED_TYPE(Char16, Char16Ty)\r
-\r
-// 'char32_t' in C++\r
-UNSIGNED_TYPE(Char32, Char32Ty)\r
-\r
-// 'unsigned short'\r
-UNSIGNED_TYPE(UShort, UnsignedShortTy)\r
-\r
-// 'unsigned int'\r
-UNSIGNED_TYPE(UInt, UnsignedIntTy)\r
-\r
-// 'unsigned long'\r
-UNSIGNED_TYPE(ULong, UnsignedLongTy)\r
-\r
-// 'unsigned long long'\r
-UNSIGNED_TYPE(ULongLong, UnsignedLongLongTy)\r
-\r
-// '__uint128_t'\r
-UNSIGNED_TYPE(UInt128, UnsignedInt128Ty)\r
-\r
-//===- Signed Types -------------------------------------------------------===//\r
-\r
-// 'char' for targets where it's signed\r
-SHARED_SINGLETON_TYPE(SIGNED_TYPE(Char_S, CharTy))\r
-\r
-// 'signed char', explicitly qualified\r
-SIGNED_TYPE(SChar, SignedCharTy)\r
-\r
-// 'wchar_t' for targets where it's signed\r
-SHARED_SINGLETON_TYPE(SIGNED_TYPE(WChar_S, WCharTy))\r
-\r
-// 'short' or 'signed short'\r
-SIGNED_TYPE(Short, ShortTy)\r
-\r
-// 'int' or 'signed int'\r
-SIGNED_TYPE(Int, IntTy)\r
-\r
-// 'long' or 'signed long'\r
-SIGNED_TYPE(Long, LongTy)\r
-\r
-// 'long long' or 'signed long long'\r
-SIGNED_TYPE(LongLong, LongLongTy)\r
-\r
-// '__int128_t'\r
-SIGNED_TYPE(Int128, Int128Ty)\r
-\r
-//===- Floating point types -----------------------------------------------===//\r
-\r
-// 'half' in OpenCL, '__fp16' in ARM NEON.\r
-FLOATING_TYPE(Half, HalfTy)\r
-\r
-// 'float'\r
-FLOATING_TYPE(Float, FloatTy)\r
-\r
-// 'double'\r
-FLOATING_TYPE(Double, DoubleTy)\r
-\r
-// 'long double'\r
-FLOATING_TYPE(LongDouble, LongDoubleTy)\r
-\r
-//===- Language-specific types --------------------------------------------===//\r
-\r
-// This is the type of C++0x 'nullptr'.\r
-BUILTIN_TYPE(NullPtr, NullPtrTy)\r
-\r
-// The primitive Objective C 'id' type. The user-visible 'id'\r
-// type is a typedef of an ObjCObjectPointerType to an\r
-// ObjCObjectType with this as its base. In fact, this only ever\r
-// shows up in an AST as the base type of an ObjCObjectType.\r
-BUILTIN_TYPE(ObjCId, ObjCBuiltinIdTy)\r
-\r
-// The primitive Objective C 'Class' type. The user-visible\r
-// 'Class' type is a typedef of an ObjCObjectPointerType to an\r
-// ObjCObjectType with this as its base. In fact, this only ever\r
-// shows up in an AST as the base type of an ObjCObjectType.\r
-BUILTIN_TYPE(ObjCClass, ObjCBuiltinClassTy)\r
-\r
-// The primitive Objective C 'SEL' type. The user-visible 'SEL'\r
-// type is a typedef of a PointerType to this.\r
-BUILTIN_TYPE(ObjCSel, ObjCBuiltinSelTy)\r
-\r
-// OpenCL image types.\r
-BUILTIN_TYPE(OCLImage1d, OCLImage1dTy)\r
-BUILTIN_TYPE(OCLImage1dArray, OCLImage1dArrayTy)\r
-BUILTIN_TYPE(OCLImage1dBuffer, OCLImage1dBufferTy)\r
-BUILTIN_TYPE(OCLImage2d, OCLImage2dTy)\r
-BUILTIN_TYPE(OCLImage2dArray, OCLImage2dArrayTy)\r
-BUILTIN_TYPE(OCLImage3d, OCLImage3dTy)\r
-\r
-// This represents the type of an expression whose type is\r
-// totally unknown, e.g. 'T::foo'. It is permitted for this to\r
-// appear in situations where the structure of the type is\r
-// theoretically deducible.\r
-BUILTIN_TYPE(Dependent, DependentTy)\r
-\r
-// The type of an unresolved overload set. A placeholder type.\r
-// Expressions with this type have one of the following basic\r
-// forms, with parentheses generally permitted:\r
-// foo # possibly qualified, not if an implicit access\r
-// foo # possibly qualified, not if an implicit access\r
-// &foo # possibly qualified, not if an implicit access\r
-// x->foo # only if might be a static member function\r
-// &x->foo # only if might be a static member function\r
-// &Class::foo # when a pointer-to-member; sub-expr also has this type\r
-// OverloadExpr::find can be used to analyze the expression.\r
-//\r
-// Overload should be the first placeholder type, or else change\r
-// BuiltinType::isNonOverloadPlaceholderType()\r
-PLACEHOLDER_TYPE(Overload, OverloadTy)\r
-\r
-// The type of a bound C++ non-static member function.\r
-// A placeholder type. Expressions with this type have one of the\r
-// following basic forms:\r
-// foo # if an implicit access\r
-// x->foo # if only contains non-static members\r
-PLACEHOLDER_TYPE(BoundMember, BoundMemberTy)\r
-\r
-// The type of an expression which refers to a pseudo-object,\r
-// such as those introduced by Objective C's @property or\r
-// VS.NET's __property declarations. A placeholder type. The\r
-// pseudo-object is actually accessed by emitting a call to\r
-// some sort of function or method; typically there is a pair\r
-// of a setter and a getter, with the setter used if the\r
-// pseudo-object reference is used syntactically as the\r
-// left-hand-side of an assignment operator.\r
-//\r
-// A pseudo-object reference naming an Objective-C @property is\r
-// always a dot access with a base of object-pointer type,\r
-// e.g. 'x.foo'.\r
-//\r
-// In VS.NET, a __property declaration creates an implicit\r
-// member with an associated name, which can then be named\r
-// in any of the normal ways an ordinary member could be.\r
-PLACEHOLDER_TYPE(PseudoObject, PseudoObjectTy)\r
-\r
-// __builtin_any_type. A placeholder type. Useful for clients\r
-// like debuggers that don't know what type to give something.\r
-// Only a small number of operations are valid on expressions of\r
-// unknown type, most notably explicit casts.\r
-PLACEHOLDER_TYPE(UnknownAny, UnknownAnyTy)\r
-\r
-PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy)\r
-\r
-// The type of a cast which, in ARC, would normally require a\r
-// __bridge, but which might be okay depending on the immediate\r
-// context.\r
-PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy)\r
-\r
-#ifdef LAST_BUILTIN_TYPE\r
-LAST_BUILTIN_TYPE(ARCUnbridgedCast)\r
-#undef LAST_BUILTIN_TYPE\r
-#endif\r
-\r
-#undef SHARED_SINGLETON_TYPE\r
-#undef PLACEHOLDER_TYPE\r
-#undef FLOATING_TYPE\r
-#undef SIGNED_TYPE\r
-#undef UNSIGNED_TYPE\r
-#undef BUILTIN_TYPE\r
+//===-- 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
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.
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);
}
-//===--- Specifiers.h - Declaration and Type Specifiers ---------*- C++ -*-===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-///\r
-/// \file\r
-/// \brief Defines various enumerations that describe declaration and\r
-/// type specifiers.\r
-///\r
-//===----------------------------------------------------------------------===//\r
-\r
-#ifndef LLVM_CLANG_BASIC_SPECIFIERS_H\r
-#define LLVM_CLANG_BASIC_SPECIFIERS_H\r
-\r
-namespace clang {\r
- /// \brief Specifies the width of a type, e.g., short, long, or long long.\r
- enum TypeSpecifierWidth {\r
- TSW_unspecified,\r
- TSW_short,\r
- TSW_long,\r
- TSW_longlong\r
- };\r
- \r
- /// \brief Specifies the signedness of a type, e.g., signed or unsigned.\r
- enum TypeSpecifierSign {\r
- TSS_unspecified,\r
- TSS_signed,\r
- TSS_unsigned\r
- };\r
- \r
- /// \brief Specifies the kind of type.\r
- enum TypeSpecifierType {\r
- TST_unspecified,\r
- TST_void,\r
- TST_char,\r
- TST_wchar, // C++ wchar_t\r
- TST_char16, // C++0x char16_t\r
- TST_char32, // C++0x char32_t\r
- TST_int,\r
- TST_int128,\r
- TST_half, // OpenCL half, ARM NEON __fp16\r
- TST_float,\r
- TST_double,\r
- TST_bool, // _Bool\r
- TST_decimal32, // _Decimal32\r
- TST_decimal64, // _Decimal64\r
- TST_decimal128, // _Decimal128\r
- TST_enum,\r
- TST_union,\r
- TST_struct,\r
- TST_class, // C++ class type\r
- TST_interface, // C++ (Microsoft-specific) __interface type\r
- TST_typename, // Typedef, C++ class-name or enum name, etc.\r
- TST_typeofType,\r
- TST_typeofExpr,\r
- TST_decltype, // C++0x decltype\r
- TST_underlyingType, // __underlying_type for C++0x\r
- TST_auto, // C++0x auto\r
- TST_unknown_anytype, // __unknown_anytype extension\r
- TST_atomic, // C11 _Atomic\r
- TST_image1d_t, // OpenCL image1d_t\r
- TST_image1d_array_t, // OpenCL image1d_array_t\r
- TST_image1d_buffer_t, // OpenCL image1d_buffer_t\r
- TST_image2d_t, // OpenCL image2d_t\r
- TST_image2d_array_t, // OpenCL image2d_array_t\r
- TST_image3d_t, // OpenCL image3d_t\r
- TST_error // erroneous type\r
- };\r
- \r
- /// \brief Structure that packs information about the type specifiers that\r
- /// were written in a particular type specifier sequence.\r
- struct WrittenBuiltinSpecs {\r
- /*DeclSpec::TST*/ unsigned Type : 6;\r
- /*DeclSpec::TSS*/ unsigned Sign : 2;\r
- /*DeclSpec::TSW*/ unsigned Width : 2;\r
- bool ModeAttr : 1;\r
- }; \r
-\r
- /// \brief A C++ access specifier (public, private, protected), plus the\r
- /// special value "none" which means different things in different contexts.\r
- enum AccessSpecifier {\r
- AS_public,\r
- AS_protected,\r
- AS_private,\r
- AS_none\r
- };\r
-\r
- /// \brief The categorization of expression values, currently following the\r
- /// C++11 scheme.\r
- enum ExprValueKind {\r
- /// \brief An r-value expression (a pr-value in the C++11 taxonomy)\r
- /// produces a temporary value.\r
- VK_RValue,\r
-\r
- /// \brief An l-value expression is a reference to an object with\r
- /// independent storage.\r
- VK_LValue,\r
-\r
- /// \brief An x-value expression is a reference to an object with\r
- /// independent storage but which can be "moved", i.e.\r
- /// efficiently cannibalized for its resources.\r
- VK_XValue\r
- };\r
-\r
- /// \brief A further classification of the kind of object referenced by an\r
- /// l-value or x-value.\r
- enum ExprObjectKind {\r
- /// An ordinary object is located at an address in memory.\r
- OK_Ordinary,\r
-\r
- /// A bitfield object is a bitfield on a C or C++ record.\r
- OK_BitField,\r
-\r
- /// A vector component is an element or range of elements on a vector.\r
- OK_VectorComponent,\r
-\r
- /// An Objective-C property is a logical field of an Objective-C\r
- /// object which is read and written via Objective-C method calls.\r
- OK_ObjCProperty,\r
- \r
- /// An Objective-C array/dictionary subscripting which reads an\r
- /// object or writes at the subscripted array/dictionary element via\r
- /// Objective-C method calls.\r
- OK_ObjCSubscript\r
- };\r
-\r
- // \brief Describes the kind of template specialization that a\r
- // particular template specialization declaration represents.\r
- enum TemplateSpecializationKind {\r
- /// This template specialization was formed from a template-id but\r
- /// has not yet been declared, defined, or instantiated.\r
- TSK_Undeclared = 0,\r
- /// This template specialization was implicitly instantiated from a\r
- /// template. (C++ [temp.inst]).\r
- TSK_ImplicitInstantiation,\r
- /// This template specialization was declared or defined by an\r
- /// explicit specialization (C++ [temp.expl.spec]) or partial\r
- /// specialization (C++ [temp.class.spec]).\r
- TSK_ExplicitSpecialization,\r
- /// This template specialization was instantiated from a template\r
- /// due to an explicit instantiation declaration request\r
- /// (C++0x [temp.explicit]).\r
- TSK_ExplicitInstantiationDeclaration,\r
- /// This template specialization was instantiated from a template\r
- /// due to an explicit instantiation definition request\r
- /// (C++ [temp.explicit]).\r
- TSK_ExplicitInstantiationDefinition\r
- };\r
-\r
- /// \brief Storage classes.\r
- enum StorageClass {\r
- // These are legal on both functions and variables.\r
- SC_None,\r
- SC_Extern,\r
- SC_Static,\r
- SC_PrivateExtern,\r
-\r
- // These are only legal on variables.\r
- SC_OpenCLWorkGroupLocal,\r
- SC_Auto,\r
- SC_Register\r
- };\r
-\r
- /// \brief Checks whether the given storage class is legal for functions.\r
- inline bool isLegalForFunction(StorageClass SC) {\r
- return SC <= SC_PrivateExtern;\r
- }\r
-\r
- /// \brief Checks whether the given storage class is legal for variables.\r
- inline bool isLegalForVariable(StorageClass SC) {\r
- return true;\r
- }\r
-\r
- /// \brief In-class initialization styles for non-static data members.\r
- enum InClassInitStyle {\r
- ICIS_NoInit, ///< No in-class initializer.\r
- ICIS_CopyInit, ///< Copy initialization.\r
- ICIS_ListInit ///< Direct list-initialization.\r
- };\r
-\r
- /// \brief CallingConv - Specifies the calling convention that a function uses.\r
- enum CallingConv {\r
- CC_Default,\r
- CC_C, // __attribute__((cdecl))\r
- CC_X86StdCall, // __attribute__((stdcall))\r
- CC_X86FastCall, // __attribute__((fastcall))\r
- CC_X86ThisCall, // __attribute__((thiscall))\r
- CC_X86Pascal, // __attribute__((pascal))\r
- CC_AAPCS, // __attribute__((pcs("aapcs")))\r
- CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))\r
- CC_PnaclCall // __attribute__((pnaclcall))\r
- };\r
-\r
-} // end namespace clang\r
-\r
-#endif // LLVM_CLANG_BASIC_SPECIFIERS_H\r
+//===--- 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
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)
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
/*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;
-//===- ASTBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This header defines Bitcode enum values for Clang serialized AST files.\r
-//\r
-// The enum values defined in this file should be considered permanent. If\r
-// new features are added, they should have values added at the end of the\r
-// respective lists.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-#ifndef LLVM_CLANG_FRONTEND_PCHBITCODES_H\r
-#define LLVM_CLANG_FRONTEND_PCHBITCODES_H\r
-\r
-#include "clang/AST/Type.h"\r
-#include "llvm/ADT/DenseMap.h"\r
-#include "llvm/Bitcode/BitCodes.h"\r
-#include "llvm/Support/DataTypes.h"\r
-\r
-namespace clang {\r
- namespace serialization {\r
- /// \brief AST file major version number supported by this version of\r
- /// Clang.\r
- ///\r
- /// Whenever the AST file format changes in a way that makes it\r
- /// incompatible with previous versions (such that a reader\r
- /// designed for the previous version could not support reading\r
- /// the new version), this number should be increased.\r
- ///\r
- /// Version 4 of AST files also requires that the version control branch and\r
- /// revision match exactly, since there is no backward compatibility of\r
- /// AST files at this time.\r
- const unsigned VERSION_MAJOR = 5;\r
-\r
- /// \brief AST file minor version number supported by this version of\r
- /// Clang.\r
- ///\r
- /// Whenever the AST format changes in a way that is still\r
- /// compatible with previous versions (such that a reader designed\r
- /// for the previous version could still support reading the new\r
- /// version by ignoring new kinds of subblocks), this number\r
- /// should be increased.\r
- const unsigned VERSION_MINOR = 0;\r
-\r
- /// \brief An ID number that refers to an identifier in an AST file.\r
- /// \r
- /// The ID numbers of identifiers are consecutive (in order of discovery)\r
- /// and start at 1. 0 is reserved for NULL.\r
- typedef uint32_t IdentifierID;\r
- \r
- /// \brief An ID number that refers to a declaration in an AST file.\r
- ///\r
- /// The ID numbers of declarations are consecutive (in order of\r
- /// discovery), with values below NUM_PREDEF_DECL_IDS being reserved. \r
- /// At the start of a chain of precompiled headers, declaration ID 1 is \r
- /// used for the translation unit declaration.\r
- typedef uint32_t DeclID;\r
-\r
- /// \brief a Decl::Kind/DeclID pair.\r
- typedef std::pair<uint32_t, DeclID> KindDeclIDPair;\r
-\r
- // FIXME: Turn these into classes so we can have some type safety when\r
- // we go from local ID to global and vice-versa.\r
- typedef DeclID LocalDeclID;\r
- typedef DeclID GlobalDeclID;\r
-\r
- /// \brief An ID number that refers to a type in an AST file.\r
- ///\r
- /// The ID of a type is partitioned into two parts: the lower\r
- /// three bits are used to store the const/volatile/restrict\r
- /// qualifiers (as with QualType) and the upper bits provide a\r
- /// type index. The type index values are partitioned into two\r
- /// sets. The values below NUM_PREDEF_TYPE_IDs are predefined type\r
- /// IDs (based on the PREDEF_TYPE_*_ID constants), with 0 as a\r
- /// placeholder for "no type". Values from NUM_PREDEF_TYPE_IDs are\r
- /// other types that have serialized representations.\r
- typedef uint32_t TypeID;\r
-\r
- /// \brief A type index; the type ID with the qualifier bits removed.\r
- class TypeIdx {\r
- uint32_t Idx;\r
- public:\r
- TypeIdx() : Idx(0) { }\r
- explicit TypeIdx(uint32_t index) : Idx(index) { }\r
-\r
- uint32_t getIndex() const { return Idx; }\r
- TypeID asTypeID(unsigned FastQuals) const {\r
- if (Idx == uint32_t(-1))\r
- return TypeID(-1);\r
- \r
- return (Idx << Qualifiers::FastWidth) | FastQuals;\r
- }\r
- static TypeIdx fromTypeID(TypeID ID) {\r
- if (ID == TypeID(-1))\r
- return TypeIdx(-1);\r
- \r
- return TypeIdx(ID >> Qualifiers::FastWidth);\r
- }\r
- };\r
-\r
- /// A structure for putting "fast"-unqualified QualTypes into a\r
- /// DenseMap. This uses the standard pointer hash function.\r
- struct UnsafeQualTypeDenseMapInfo {\r
- static inline bool isEqual(QualType A, QualType B) { return A == B; }\r
- static inline QualType getEmptyKey() {\r
- return QualType::getFromOpaquePtr((void*) 1);\r
- }\r
- static inline QualType getTombstoneKey() {\r
- return QualType::getFromOpaquePtr((void*) 2);\r
- }\r
- static inline unsigned getHashValue(QualType T) {\r
- assert(!T.getLocalFastQualifiers() && \r
- "hash invalid for types with fast quals");\r
- uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());\r
- return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);\r
- }\r
- };\r
-\r
- /// \brief An ID number that refers to an identifier in an AST file.\r
- typedef uint32_t IdentID;\r
-\r
- /// \brief The number of predefined identifier IDs.\r
- const unsigned int NUM_PREDEF_IDENT_IDS = 1;\r
-\r
- /// \brief An ID number that refers to a macro in an AST file.\r
- typedef uint32_t MacroID;\r
- \r
- /// \brief The number of predefined macro IDs.\r
- const unsigned int NUM_PREDEF_MACRO_IDS = 1;\r
-\r
- /// \brief An ID number that refers to an ObjC selector in an AST file.\r
- typedef uint32_t SelectorID;\r
-\r
- /// \brief The number of predefined selector IDs.\r
- const unsigned int NUM_PREDEF_SELECTOR_IDS = 1;\r
- \r
- /// \brief An ID number that refers to a set of CXXBaseSpecifiers in an \r
- /// AST file.\r
- typedef uint32_t CXXBaseSpecifiersID;\r
- \r
- /// \brief An ID number that refers to an entity in the detailed\r
- /// preprocessing record.\r
- typedef uint32_t PreprocessedEntityID;\r
-\r
- /// \brief An ID number that refers to a submodule in a module file.\r
- typedef uint32_t SubmoduleID;\r
- \r
- /// \brief The number of predefined submodule IDs.\r
- const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1;\r
-\r
- /// \brief Source range/offset of a preprocessed entity.\r
- struct PPEntityOffset {\r
- /// \brief Raw source location of beginning of range.\r
- unsigned Begin;\r
- /// \brief Raw source location of end of range.\r
- unsigned End;\r
- /// \brief Offset in the AST file.\r
- uint32_t BitOffset;\r
-\r
- PPEntityOffset(SourceRange R, uint32_t BitOffset)\r
- : Begin(R.getBegin().getRawEncoding()),\r
- End(R.getEnd().getRawEncoding()),\r
- BitOffset(BitOffset) { }\r
- };\r
-\r
- /// \brief Source range/offset of a preprocessed entity.\r
- struct DeclOffset {\r
- /// \brief Raw source location.\r
- unsigned Loc;\r
- /// \brief Offset in the AST file.\r
- uint32_t BitOffset;\r
-\r
- DeclOffset() : Loc(0), BitOffset(0) { }\r
- DeclOffset(SourceLocation Loc, uint32_t BitOffset)\r
- : Loc(Loc.getRawEncoding()),\r
- BitOffset(BitOffset) { }\r
- void setLocation(SourceLocation L) {\r
- Loc = L.getRawEncoding();\r
- }\r
- };\r
-\r
- /// \brief The number of predefined preprocessed entity IDs.\r
- const unsigned int NUM_PREDEF_PP_ENTITY_IDS = 1;\r
-\r
- /// \brief Describes the various kinds of blocks that occur within\r
- /// an AST file.\r
- enum BlockIDs {\r
- /// \brief The AST block, which acts as a container around the\r
- /// full AST block.\r
- AST_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,\r
-\r
- /// \brief The block containing information about the source\r
- /// manager.\r
- SOURCE_MANAGER_BLOCK_ID,\r
-\r
- /// \brief The block containing information about the\r
- /// preprocessor.\r
- PREPROCESSOR_BLOCK_ID,\r
-\r
- /// \brief The block containing the definitions of all of the\r
- /// types and decls used within the AST file.\r
- DECLTYPES_BLOCK_ID,\r
-\r
- /// \brief The block containing DECL_UPDATES records.\r
- DECL_UPDATES_BLOCK_ID,\r
- \r
- /// \brief The block containing the detailed preprocessing record.\r
- PREPROCESSOR_DETAIL_BLOCK_ID,\r
- \r
- /// \brief The block containing the submodule structure.\r
- SUBMODULE_BLOCK_ID,\r
-\r
- /// \brief The block containing comments.\r
- COMMENTS_BLOCK_ID,\r
-\r
- /// \brief The control block, which contains all of the\r
- /// information that needs to be validated prior to committing\r
- /// to loading the AST file.\r
- CONTROL_BLOCK_ID,\r
-\r
- /// \brief The block of input files, which were used as inputs\r
- /// to create this AST file.\r
- ///\r
- /// This block is part of the control block.\r
- INPUT_FILES_BLOCK_ID\r
- };\r
-\r
- /// \brief Record types that occur within the control block.\r
- enum ControlRecordTypes {\r
- /// \brief AST file metadata, including the AST file version number\r
- /// and information about the compiler used to build this AST file.\r
- METADATA = 1,\r
-\r
- /// \brief Record code for the list of other AST files imported by\r
- /// this AST file.\r
- IMPORTS = 2,\r
-\r
- /// \brief Record code for the language options table.\r
- ///\r
- /// The record with this code contains the contents of the\r
- /// LangOptions structure. We serialize the entire contents of\r
- /// the structure, and let the reader decide which options are\r
- /// actually important to check.\r
- LANGUAGE_OPTIONS = 3,\r
-\r
- /// \brief Record code for the target options table.\r
- TARGET_OPTIONS = 4,\r
-\r
- /// \brief Record code for the original file that was used to\r
- /// generate the AST file, including both its file ID and its\r
- /// name.\r
- ORIGINAL_FILE = 5,\r
- \r
- /// \brief The directory that the PCH was originally created in.\r
- ORIGINAL_PCH_DIR = 6,\r
-\r
- /// \brief Record code for file ID of the file or buffer that was used to\r
- /// generate the AST file.\r
- ORIGINAL_FILE_ID = 7,\r
-\r
- /// \brief Offsets into the input-files block where input files\r
- /// reside.\r
- INPUT_FILE_OFFSETS = 8,\r
-\r
- /// \brief Record code for the diagnostic options table.\r
- DIAGNOSTIC_OPTIONS = 9,\r
-\r
- /// \brief Record code for the filesystem options table.\r
- FILE_SYSTEM_OPTIONS = 10,\r
-\r
- /// \brief Record code for the headers search options table.\r
- HEADER_SEARCH_OPTIONS = 11,\r
-\r
- /// \brief Record code for the preprocessor options table.\r
- PREPROCESSOR_OPTIONS = 12\r
- };\r
-\r
- /// \brief Record types that occur within the input-files block\r
- /// inside the control block.\r
- enum InputFileRecordTypes {\r
- /// \brief An input file.\r
- INPUT_FILE = 1\r
- };\r
-\r
- /// \brief Record types that occur within the AST block itself.\r
- enum ASTRecordTypes {\r
- /// \brief Record code for the offsets of each type.\r
- ///\r
- /// The TYPE_OFFSET constant describes the record that occurs\r
- /// within the AST block. The record itself is an array of offsets that\r
- /// point into the declarations and types block (identified by \r
- /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID\r
- /// of a type. For a given type ID @c T, the lower three bits of\r
- /// @c T are its qualifiers (const, volatile, restrict), as in\r
- /// the QualType class. The upper bits, after being shifted and\r
- /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the\r
- /// TYPE_OFFSET block to determine the offset of that type's\r
- /// corresponding record within the DECLTYPES_BLOCK_ID block.\r
- TYPE_OFFSET = 1,\r
-\r
- /// \brief Record code for the offsets of each decl.\r
- ///\r
- /// The DECL_OFFSET constant describes the record that occurs\r
- /// within the block identified by DECL_OFFSETS_BLOCK_ID within\r
- /// the AST block. The record itself is an array of offsets that\r
- /// point into the declarations and types block (identified by\r
- /// DECLTYPES_BLOCK_ID). The declaration ID is an index into this\r
- /// record, after subtracting one to account for the use of\r
- /// declaration ID 0 for a NULL declaration pointer. Index 0 is\r
- /// reserved for the translation unit declaration.\r
- DECL_OFFSET = 2,\r
-\r
- /// \brief Record code for the table of offsets of each\r
- /// identifier ID.\r
- ///\r
- /// The offset table contains offsets into the blob stored in\r
- /// the IDENTIFIER_TABLE record. Each offset points to the\r
- /// NULL-terminated string that corresponds to that identifier.\r
- IDENTIFIER_OFFSET = 3,\r
-\r
- /// \brief This is so that older clang versions, before the introduction\r
- /// of the control block, can read and reject the newer PCH format.\r
- /// *DON"T CHANGE THIS NUMBER*.\r
- METADATA_OLD_FORMAT = 4,\r
-\r
- /// \brief Record code for the identifier table.\r
- ///\r
- /// The identifier table is a simple blob that contains\r
- /// NULL-terminated strings for all of the identifiers\r
- /// referenced by the AST file. The IDENTIFIER_OFFSET table\r
- /// contains the mapping from identifier IDs to the characters\r
- /// in this blob. Note that the starting offsets of all of the\r
- /// identifiers are odd, so that, when the identifier offset\r
- /// table is loaded in, we can use the low bit to distinguish\r
- /// between offsets (for unresolved identifier IDs) and\r
- /// IdentifierInfo pointers (for already-resolved identifier\r
- /// IDs).\r
- IDENTIFIER_TABLE = 5,\r
-\r
- /// \brief Record code for the array of external definitions.\r
- ///\r
- /// The AST file contains a list of all of the unnamed external\r
- /// definitions present within the parsed headers, stored as an\r
- /// array of declaration IDs. These external definitions will be\r
- /// reported to the AST consumer after the AST file has been\r
- /// read, since their presence can affect the semantics of the\r
- /// program (e.g., for code generation).\r
- EXTERNAL_DEFINITIONS = 6,\r
-\r
- /// \brief Record code for the set of non-builtin, special\r
- /// types.\r
- ///\r
- /// This record contains the type IDs for the various type nodes\r
- /// that are constructed during semantic analysis (e.g.,\r
- /// __builtin_va_list). The SPECIAL_TYPE_* constants provide\r
- /// offsets into this record.\r
- SPECIAL_TYPES = 7,\r
-\r
- /// \brief Record code for the extra statistics we gather while\r
- /// generating an AST file.\r
- STATISTICS = 8,\r
-\r
- /// \brief Record code for the array of tentative definitions.\r
- TENTATIVE_DEFINITIONS = 9,\r
-\r
- /// \brief Record code for the array of locally-scoped external\r
- /// declarations.\r
- LOCALLY_SCOPED_EXTERNAL_DECLS = 10,\r
-\r
- /// \brief Record code for the table of offsets into the\r
- /// Objective-C method pool.\r
- SELECTOR_OFFSETS = 11,\r
-\r
- /// \brief Record code for the Objective-C method pool,\r
- METHOD_POOL = 12,\r
-\r
- /// \brief The value of the next __COUNTER__ to dispense.\r
- /// [PP_COUNTER_VALUE, Val]\r
- PP_COUNTER_VALUE = 13,\r
-\r
- /// \brief Record code for the table of offsets into the block\r
- /// of source-location information.\r
- SOURCE_LOCATION_OFFSETS = 14,\r
-\r
- /// \brief Record code for the set of source location entries\r
- /// that need to be preloaded by the AST reader.\r
- ///\r
- /// This set contains the source location entry for the\r
- /// predefines buffer and for any file entries that need to be\r
- /// preloaded.\r
- SOURCE_LOCATION_PRELOADS = 15,\r
-\r
- /// \brief Record code for the set of ext_vector type names.\r
- EXT_VECTOR_DECLS = 16,\r
- \r
- /// \brief Record code for the array of unused file scoped decls.\r
- UNUSED_FILESCOPED_DECLS = 17,\r
- \r
- /// \brief Record code for the table of offsets to entries in the\r
- /// preprocessing record.\r
- PPD_ENTITIES_OFFSETS = 18,\r
-\r
- /// \brief Record code for the array of VTable uses.\r
- VTABLE_USES = 19,\r
-\r
- /// \brief Record code for the array of dynamic classes.\r
- DYNAMIC_CLASSES = 20,\r
-\r
- /// \brief Record code for referenced selector pool.\r
- REFERENCED_SELECTOR_POOL = 21,\r
-\r
- /// \brief Record code for an update to the TU's lexically contained\r
- /// declarations.\r
- TU_UPDATE_LEXICAL = 22,\r
- \r
- /// \brief Record code for the array describing the locations (in the\r
- /// LOCAL_REDECLARATIONS record) of the redeclaration chains, indexed by\r
- /// the first known ID.\r
- LOCAL_REDECLARATIONS_MAP = 23,\r
-\r
- /// \brief Record code for declarations that Sema keeps references of.\r
- SEMA_DECL_REFS = 24,\r
-\r
- /// \brief Record code for weak undeclared identifiers.\r
- WEAK_UNDECLARED_IDENTIFIERS = 25,\r
-\r
- /// \brief Record code for pending implicit instantiations.\r
- PENDING_IMPLICIT_INSTANTIATIONS = 26,\r
-\r
- /// \brief Record code for a decl replacement block.\r
- ///\r
- /// If a declaration is modified after having been deserialized, and then\r
- /// written to a dependent AST file, its ID and offset must be added to\r
- /// the replacement block.\r
- DECL_REPLACEMENTS = 27,\r
-\r
- /// \brief Record code for an update to a decl context's lookup table.\r
- ///\r
- /// In practice, this should only be used for the TU and namespaces.\r
- UPDATE_VISIBLE = 28,\r
-\r
- /// \brief Record for offsets of DECL_UPDATES records for declarations\r
- /// that were modified after being deserialized and need updates.\r
- DECL_UPDATE_OFFSETS = 29,\r
-\r
- /// \brief Record of updates for a declaration that was modified after\r
- /// being deserialized.\r
- DECL_UPDATES = 30,\r
- \r
- /// \brief Record code for the table of offsets to CXXBaseSpecifier\r
- /// sets.\r
- CXX_BASE_SPECIFIER_OFFSETS = 31,\r
-\r
- /// \brief Record code for \#pragma diagnostic mappings.\r
- DIAG_PRAGMA_MAPPINGS = 32,\r
-\r
- /// \brief Record code for special CUDA declarations.\r
- CUDA_SPECIAL_DECL_REFS = 33,\r
- \r
- /// \brief Record code for header search information.\r
- HEADER_SEARCH_TABLE = 34,\r
-\r
- /// \brief Record code for floating point \#pragma options.\r
- FP_PRAGMA_OPTIONS = 35,\r
-\r
- /// \brief Record code for enabled OpenCL extensions.\r
- OPENCL_EXTENSIONS = 36,\r
-\r
- /// \brief The list of delegating constructor declarations.\r
- DELEGATING_CTORS = 37,\r
-\r
- /// \brief Record code for the set of known namespaces, which are used\r
- /// for typo correction.\r
- KNOWN_NAMESPACES = 38,\r
-\r
- /// \brief Record code for the remapping information used to relate\r
- /// loaded modules to the various offsets and IDs(e.g., source location \r
- /// offests, declaration and type IDs) that are used in that module to\r
- /// refer to other modules.\r
- MODULE_OFFSET_MAP = 39,\r
-\r
- /// \brief Record code for the source manager line table information,\r
- /// which stores information about \#line directives.\r
- SOURCE_MANAGER_LINE_TABLE = 40,\r
-\r
- /// \brief Record code for map of Objective-C class definition IDs to the \r
- /// ObjC categories in a module that are attached to that class.\r
- OBJC_CATEGORIES_MAP = 41,\r
-\r
- /// \brief Record code for a file sorted array of DeclIDs in a module.\r
- FILE_SORTED_DECLS = 42,\r
- \r
- /// \brief Record code for an array of all of the (sub)modules that were\r
- /// imported by the AST file.\r
- IMPORTED_MODULES = 43,\r
- \r
- /// \brief Record code for the set of merged declarations in an AST file.\r
- MERGED_DECLARATIONS = 44,\r
- \r
- /// \brief Record code for the array of redeclaration chains.\r
- ///\r
- /// This array can only be interpreted properly using the local \r
- /// redeclarations map.\r
- LOCAL_REDECLARATIONS = 45,\r
- \r
- /// \brief Record code for the array of Objective-C categories (including\r
- /// extensions).\r
- ///\r
- /// This array can only be interpreted properly using the Objective-C\r
- /// categories map.\r
- OBJC_CATEGORIES = 46,\r
-\r
- /// \brief Record code for the table of offsets of each macro ID.\r
- ///\r
- /// The offset table contains offsets into the blob stored in\r
- /// the preprocessor block. Each offset points to the corresponding\r
- /// macro definition.\r
- MACRO_OFFSET = 47,\r
-\r
- /// \brief Record of updates for a macro that was modified after\r
- /// being deserialized.\r
- MACRO_UPDATES = 48\r
- };\r
-\r
- /// \brief Record types used within a source manager block.\r
- enum SourceManagerRecordTypes {\r
- /// \brief Describes a source location entry (SLocEntry) for a\r
- /// file.\r
- SM_SLOC_FILE_ENTRY = 1,\r
- /// \brief Describes a source location entry (SLocEntry) for a\r
- /// buffer.\r
- SM_SLOC_BUFFER_ENTRY = 2,\r
- /// \brief Describes a blob that contains the data for a buffer\r
- /// entry. This kind of record always directly follows a\r
- /// SM_SLOC_BUFFER_ENTRY record or a SM_SLOC_FILE_ENTRY with an\r
- /// overridden buffer.\r
- SM_SLOC_BUFFER_BLOB = 3,\r
- /// \brief Describes a source location entry (SLocEntry) for a\r
- /// macro expansion.\r
- SM_SLOC_EXPANSION_ENTRY = 4\r
- };\r
-\r
- /// \brief Record types used within a preprocessor block.\r
- enum PreprocessorRecordTypes {\r
- // The macros in the PP section are a PP_MACRO_* instance followed by a\r
- // list of PP_TOKEN instances for each token in the definition.\r
-\r
- /// \brief An object-like macro definition.\r
- /// [PP_MACRO_OBJECT_LIKE, IdentInfoID, SLoc, IsUsed]\r
- PP_MACRO_OBJECT_LIKE = 1,\r
-\r
- /// \brief A function-like macro definition.\r
- /// [PP_MACRO_FUNCTION_LIKE, \<ObjectLikeStuff>, IsC99Varargs,\r
- /// IsGNUVarars, NumArgs, ArgIdentInfoID* ]\r
- PP_MACRO_FUNCTION_LIKE = 2,\r
-\r
- /// \brief Describes one token.\r
- /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]\r
- PP_TOKEN = 3\r
- };\r
-\r
- /// \brief Record types used within a preprocessor detail block.\r
- enum PreprocessorDetailRecordTypes {\r
- /// \brief Describes a macro expansion within the preprocessing record.\r
- PPD_MACRO_EXPANSION = 0,\r
- \r
- /// \brief Describes a macro definition within the preprocessing record.\r
- PPD_MACRO_DEFINITION = 1,\r
- \r
- /// \brief Describes an inclusion directive within the preprocessing\r
- /// record.\r
- PPD_INCLUSION_DIRECTIVE = 2\r
- };\r
- \r
- /// \brief Record types used within a submodule description block.\r
- enum SubmoduleRecordTypes {\r
- /// \brief Metadata for submodules as a whole.\r
- SUBMODULE_METADATA = 0,\r
- /// \brief Defines the major attributes of a submodule, including its\r
- /// name and parent.\r
- SUBMODULE_DEFINITION = 1,\r
- /// \brief Specifies the umbrella header used to create this module,\r
- /// if any.\r
- SUBMODULE_UMBRELLA_HEADER = 2,\r
- /// \brief Specifies a header that falls into this (sub)module.\r
- SUBMODULE_HEADER = 3,\r
- /// \brief Specifies a top-level header that falls into this (sub)module.\r
- SUBMODULE_TOPHEADER = 4,\r
- /// \brief Specifies an umbrella directory.\r
- SUBMODULE_UMBRELLA_DIR = 5,\r
- /// \brief Specifies the submodules that are imported by this \r
- /// submodule.\r
- SUBMODULE_IMPORTS = 6,\r
- /// \brief Specifies the submodules that are re-exported from this \r
- /// submodule.\r
- SUBMODULE_EXPORTS = 7,\r
- /// \brief Specifies a required feature.\r
- SUBMODULE_REQUIRES = 8,\r
- /// \brief Specifies a header that has been explicitly excluded\r
- /// from this submodule.\r
- SUBMODULE_EXCLUDED_HEADER = 9\r
- };\r
-\r
- /// \brief Record types used within a comments block.\r
- enum CommentRecordTypes {\r
- COMMENTS_RAW_COMMENT = 0\r
- };\r
-\r
- /// \defgroup ASTAST AST file AST constants\r
- ///\r
- /// The constants in this group describe various components of the\r
- /// abstract syntax tree within an AST file.\r
- ///\r
- /// @{\r
-\r
- /// \brief Predefined type IDs.\r
- ///\r
- /// These type IDs correspond to predefined types in the AST\r
- /// context, such as built-in types (int) and special place-holder\r
- /// types (the \<overload> and \<dependent> type markers). Such\r
- /// types are never actually serialized, since they will be built\r
- /// by the AST context when it is created.\r
- enum PredefinedTypeIDs {\r
- /// \brief The NULL type.\r
- PREDEF_TYPE_NULL_ID = 0,\r
- /// \brief The void type.\r
- PREDEF_TYPE_VOID_ID = 1,\r
- /// \brief The 'bool' or '_Bool' type.\r
- PREDEF_TYPE_BOOL_ID = 2,\r
- /// \brief The 'char' type, when it is unsigned.\r
- PREDEF_TYPE_CHAR_U_ID = 3,\r
- /// \brief The 'unsigned char' type.\r
- PREDEF_TYPE_UCHAR_ID = 4,\r
- /// \brief The 'unsigned short' type.\r
- PREDEF_TYPE_USHORT_ID = 5,\r
- /// \brief The 'unsigned int' type.\r
- PREDEF_TYPE_UINT_ID = 6,\r
- /// \brief The 'unsigned long' type.\r
- PREDEF_TYPE_ULONG_ID = 7,\r
- /// \brief The 'unsigned long long' type.\r
- PREDEF_TYPE_ULONGLONG_ID = 8,\r
- /// \brief The 'char' type, when it is signed.\r
- PREDEF_TYPE_CHAR_S_ID = 9,\r
- /// \brief The 'signed char' type.\r
- PREDEF_TYPE_SCHAR_ID = 10,\r
- /// \brief The C++ 'wchar_t' type.\r
- PREDEF_TYPE_WCHAR_ID = 11,\r
- /// \brief The (signed) 'short' type.\r
- PREDEF_TYPE_SHORT_ID = 12,\r
- /// \brief The (signed) 'int' type.\r
- PREDEF_TYPE_INT_ID = 13,\r
- /// \brief The (signed) 'long' type.\r
- PREDEF_TYPE_LONG_ID = 14,\r
- /// \brief The (signed) 'long long' type.\r
- PREDEF_TYPE_LONGLONG_ID = 15,\r
- /// \brief The 'float' type.\r
- PREDEF_TYPE_FLOAT_ID = 16,\r
- /// \brief The 'double' type.\r
- PREDEF_TYPE_DOUBLE_ID = 17,\r
- /// \brief The 'long double' type.\r
- PREDEF_TYPE_LONGDOUBLE_ID = 18,\r
- /// \brief The placeholder type for overloaded function sets.\r
- PREDEF_TYPE_OVERLOAD_ID = 19,\r
- /// \brief The placeholder type for dependent types.\r
- PREDEF_TYPE_DEPENDENT_ID = 20,\r
- /// \brief The '__uint128_t' type.\r
- PREDEF_TYPE_UINT128_ID = 21,\r
- /// \brief The '__int128_t' type.\r
- PREDEF_TYPE_INT128_ID = 22,\r
- /// \brief The type of 'nullptr'.\r
- PREDEF_TYPE_NULLPTR_ID = 23,\r
- /// \brief The C++ 'char16_t' type.\r
- PREDEF_TYPE_CHAR16_ID = 24,\r
- /// \brief The C++ 'char32_t' type.\r
- PREDEF_TYPE_CHAR32_ID = 25,\r
- /// \brief The ObjC 'id' type.\r
- PREDEF_TYPE_OBJC_ID = 26,\r
- /// \brief The ObjC 'Class' type.\r
- PREDEF_TYPE_OBJC_CLASS = 27,\r
- /// \brief The ObjC 'SEL' type.\r
- PREDEF_TYPE_OBJC_SEL = 28,\r
- /// \brief The 'unknown any' placeholder type.\r
- PREDEF_TYPE_UNKNOWN_ANY = 29,\r
- /// \brief The placeholder type for bound member functions.\r
- PREDEF_TYPE_BOUND_MEMBER = 30,\r
- /// \brief The "auto" deduction type.\r
- PREDEF_TYPE_AUTO_DEDUCT = 31,\r
- /// \brief The "auto &&" deduction type.\r
- PREDEF_TYPE_AUTO_RREF_DEDUCT = 32,\r
- /// \brief The OpenCL 'half' / ARM NEON __fp16 type.\r
- PREDEF_TYPE_HALF_ID = 33,\r
- /// \brief ARC's unbridged-cast placeholder type.\r
- PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34,\r
- /// \brief The pseudo-object placeholder type.\r
- PREDEF_TYPE_PSEUDO_OBJECT = 35,\r
- /// \brief The __va_list_tag placeholder type.\r
- PREDEF_TYPE_VA_LIST_TAG = 36,\r
- /// \brief The placeholder type for builtin functions.\r
- PREDEF_TYPE_BUILTIN_FN = 37,\r
- /// \brief OpenCL 1d image type.\r
- PREDEF_TYPE_IMAGE1D_ID = 38,\r
- /// \brief OpenCL 1d image array type.\r
- PREDEF_TYPE_IMAGE1D_ARR_ID = 39,\r
- /// \brief OpenCL 1d image buffer type.\r
- PREDEF_TYPE_IMAGE1D_BUFF_ID = 40,\r
- /// \brief OpenCL 2d image type.\r
- PREDEF_TYPE_IMAGE2D_ID = 41,\r
- /// \brief OpenCL 2d image array type.\r
- PREDEF_TYPE_IMAGE2D_ARR_ID = 42,\r
- /// \brief OpenCL 3d image type.\r
- PREDEF_TYPE_IMAGE3D_ID = 43\r
- };\r
-\r
- /// \brief The number of predefined type IDs that are reserved for\r
- /// the PREDEF_TYPE_* constants.\r
- ///\r
- /// Type IDs for non-predefined types will start at\r
- /// NUM_PREDEF_TYPE_IDs.\r
- const unsigned NUM_PREDEF_TYPE_IDS = 100;\r
-\r
- /// \brief The number of allowed abbreviations in bits\r
- const unsigned NUM_ALLOWED_ABBREVS_SIZE = 4;\r
-\r
- /// \brief Record codes for each kind of type.\r
- ///\r
- /// These constants describe the type records that can occur within a\r
- /// block identified by DECLTYPES_BLOCK_ID in the AST file. Each\r
- /// constant describes a record for a specific type class in the\r
- /// AST.\r
- enum TypeCode {\r
- /// \brief An ExtQualType record.\r
- TYPE_EXT_QUAL = 1,\r
- /// \brief A ComplexType record.\r
- TYPE_COMPLEX = 3,\r
- /// \brief A PointerType record.\r
- TYPE_POINTER = 4,\r
- /// \brief A BlockPointerType record.\r
- TYPE_BLOCK_POINTER = 5,\r
- /// \brief An LValueReferenceType record.\r
- TYPE_LVALUE_REFERENCE = 6,\r
- /// \brief An RValueReferenceType record.\r
- TYPE_RVALUE_REFERENCE = 7,\r
- /// \brief A MemberPointerType record.\r
- TYPE_MEMBER_POINTER = 8,\r
- /// \brief A ConstantArrayType record.\r
- TYPE_CONSTANT_ARRAY = 9,\r
- /// \brief An IncompleteArrayType record.\r
- TYPE_INCOMPLETE_ARRAY = 10,\r
- /// \brief A VariableArrayType record.\r
- TYPE_VARIABLE_ARRAY = 11,\r
- /// \brief A VectorType record.\r
- TYPE_VECTOR = 12,\r
- /// \brief An ExtVectorType record.\r
- TYPE_EXT_VECTOR = 13,\r
- /// \brief A FunctionNoProtoType record.\r
- TYPE_FUNCTION_NO_PROTO = 14,\r
- /// \brief A FunctionProtoType record.\r
- TYPE_FUNCTION_PROTO = 15,\r
- /// \brief A TypedefType record.\r
- TYPE_TYPEDEF = 16,\r
- /// \brief A TypeOfExprType record.\r
- TYPE_TYPEOF_EXPR = 17,\r
- /// \brief A TypeOfType record.\r
- TYPE_TYPEOF = 18,\r
- /// \brief A RecordType record.\r
- TYPE_RECORD = 19,\r
- /// \brief An EnumType record.\r
- TYPE_ENUM = 20,\r
- /// \brief An ObjCInterfaceType record.\r
- TYPE_OBJC_INTERFACE = 21,\r
- /// \brief An ObjCObjectPointerType record.\r
- TYPE_OBJC_OBJECT_POINTER = 22,\r
- /// \brief a DecltypeType record.\r
- TYPE_DECLTYPE = 23,\r
- /// \brief An ElaboratedType record.\r
- TYPE_ELABORATED = 24,\r
- /// \brief A SubstTemplateTypeParmType record.\r
- TYPE_SUBST_TEMPLATE_TYPE_PARM = 25,\r
- /// \brief An UnresolvedUsingType record.\r
- TYPE_UNRESOLVED_USING = 26,\r
- /// \brief An InjectedClassNameType record.\r
- TYPE_INJECTED_CLASS_NAME = 27,\r
- /// \brief An ObjCObjectType record.\r
- TYPE_OBJC_OBJECT = 28,\r
- /// \brief An TemplateTypeParmType record.\r
- TYPE_TEMPLATE_TYPE_PARM = 29,\r
- /// \brief An TemplateSpecializationType record.\r
- TYPE_TEMPLATE_SPECIALIZATION = 30,\r
- /// \brief A DependentNameType record.\r
- TYPE_DEPENDENT_NAME = 31,\r
- /// \brief A DependentTemplateSpecializationType record.\r
- TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32,\r
- /// \brief A DependentSizedArrayType record.\r
- TYPE_DEPENDENT_SIZED_ARRAY = 33,\r
- /// \brief A ParenType record.\r
- TYPE_PAREN = 34,\r
- /// \brief A PackExpansionType record.\r
- TYPE_PACK_EXPANSION = 35,\r
- /// \brief An AttributedType record.\r
- TYPE_ATTRIBUTED = 36,\r
- /// \brief A SubstTemplateTypeParmPackType record.\r
- TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37,\r
- /// \brief A AutoType record.\r
- TYPE_AUTO = 38,\r
- /// \brief A UnaryTransformType record.\r
- TYPE_UNARY_TRANSFORM = 39,\r
- /// \brief An AtomicType record.\r
- TYPE_ATOMIC = 40\r
- };\r
-\r
- /// \brief The type IDs for special types constructed by semantic\r
- /// analysis.\r
- ///\r
- /// The constants in this enumeration are indices into the\r
- /// SPECIAL_TYPES record.\r
- enum SpecialTypeIDs {\r
- /// \brief CFConstantString type\r
- SPECIAL_TYPE_CF_CONSTANT_STRING = 0,\r
- /// \brief C FILE typedef type\r
- SPECIAL_TYPE_FILE = 1,\r
- /// \brief C jmp_buf typedef type\r
- SPECIAL_TYPE_JMP_BUF = 2,\r
- /// \brief C sigjmp_buf typedef type\r
- SPECIAL_TYPE_SIGJMP_BUF = 3,\r
- /// \brief Objective-C "id" redefinition type\r
- SPECIAL_TYPE_OBJC_ID_REDEFINITION = 4,\r
- /// \brief Objective-C "Class" redefinition type\r
- SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 5,\r
- /// \brief Objective-C "SEL" redefinition type\r
- SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 6,\r
- /// \brief C ucontext_t typedef type\r
- SPECIAL_TYPE_UCONTEXT_T = 7\r
- };\r
- \r
- /// \brief The number of special type IDs.\r
- const unsigned NumSpecialTypeIDs = 8;\r
-\r
- /// \brief Predefined declaration IDs.\r
- ///\r
- /// These declaration IDs correspond to predefined declarations in the AST\r
- /// context, such as the NULL declaration ID. Such declarations are never\r
- /// actually serialized, since they will be built by the AST context when \r
- /// it is created.\r
- enum PredefinedDeclIDs {\r
- /// \brief The NULL declaration.\r
- PREDEF_DECL_NULL_ID = 0,\r
- \r
- /// \brief The translation unit.\r
- PREDEF_DECL_TRANSLATION_UNIT_ID = 1,\r
- \r
- /// \brief The Objective-C 'id' type.\r
- PREDEF_DECL_OBJC_ID_ID = 2,\r
- \r
- /// \brief The Objective-C 'SEL' type.\r
- PREDEF_DECL_OBJC_SEL_ID = 3,\r
- \r
- /// \brief The Objective-C 'Class' type.\r
- PREDEF_DECL_OBJC_CLASS_ID = 4,\r
- \r
- /// \brief The Objective-C 'Protocol' type.\r
- PREDEF_DECL_OBJC_PROTOCOL_ID = 5,\r
- \r
- /// \brief The signed 128-bit integer type.\r
- PREDEF_DECL_INT_128_ID = 6,\r
-\r
- /// \brief The unsigned 128-bit integer type.\r
- PREDEF_DECL_UNSIGNED_INT_128_ID = 7,\r
- \r
- /// \brief The internal 'instancetype' typedef.\r
- PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,\r
-\r
- /// \brief The internal '__builtin_va_list' typedef.\r
- PREDEF_DECL_BUILTIN_VA_LIST_ID = 9\r
- };\r
-\r
- /// \brief The number of declaration IDs that are predefined.\r
- ///\r
- /// For more information about predefined declarations, see the\r
- /// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.\r
- const unsigned int NUM_PREDEF_DECL_IDS = 10;\r
- \r
- /// \brief Record codes for each kind of declaration.\r
- ///\r
- /// These constants describe the declaration records that can occur within\r
- /// a declarations block (identified by DECLS_BLOCK_ID). Each\r
- /// constant describes a record for a specific declaration class\r
- /// in the AST.\r
- enum DeclCode {\r
- /// \brief A TypedefDecl record.\r
- DECL_TYPEDEF = 51,\r
- /// \brief A TypeAliasDecl record.\r
- DECL_TYPEALIAS,\r
- /// \brief An EnumDecl record.\r
- DECL_ENUM,\r
- /// \brief A RecordDecl record.\r
- DECL_RECORD,\r
- /// \brief An EnumConstantDecl record.\r
- DECL_ENUM_CONSTANT,\r
- /// \brief A FunctionDecl record.\r
- DECL_FUNCTION,\r
- /// \brief A ObjCMethodDecl record.\r
- DECL_OBJC_METHOD,\r
- /// \brief A ObjCInterfaceDecl record.\r
- DECL_OBJC_INTERFACE,\r
- /// \brief A ObjCProtocolDecl record.\r
- DECL_OBJC_PROTOCOL,\r
- /// \brief A ObjCIvarDecl record.\r
- DECL_OBJC_IVAR,\r
- /// \brief A ObjCAtDefsFieldDecl record.\r
- DECL_OBJC_AT_DEFS_FIELD,\r
- /// \brief A ObjCCategoryDecl record.\r
- DECL_OBJC_CATEGORY,\r
- /// \brief A ObjCCategoryImplDecl record.\r
- DECL_OBJC_CATEGORY_IMPL,\r
- /// \brief A ObjCImplementationDecl record.\r
- DECL_OBJC_IMPLEMENTATION,\r
- /// \brief A ObjCCompatibleAliasDecl record.\r
- DECL_OBJC_COMPATIBLE_ALIAS,\r
- /// \brief A ObjCPropertyDecl record.\r
- DECL_OBJC_PROPERTY,\r
- /// \brief A ObjCPropertyImplDecl record.\r
- DECL_OBJC_PROPERTY_IMPL,\r
- /// \brief A FieldDecl record.\r
- DECL_FIELD,\r
- /// \brief A VarDecl record.\r
- DECL_VAR,\r
- /// \brief An ImplicitParamDecl record.\r
- DECL_IMPLICIT_PARAM,\r
- /// \brief A ParmVarDecl record.\r
- DECL_PARM_VAR,\r
- /// \brief A FileScopeAsmDecl record.\r
- DECL_FILE_SCOPE_ASM,\r
- /// \brief A BlockDecl record.\r
- DECL_BLOCK,\r
- /// \brief A record that stores the set of declarations that are\r
- /// lexically stored within a given DeclContext.\r
- ///\r
- /// The record itself is a blob that is an array of declaration IDs,\r
- /// in the order in which those declarations were added to the\r
- /// declaration context. This data is used when iterating over\r
- /// the contents of a DeclContext, e.g., via\r
- /// DeclContext::decls_begin() and DeclContext::decls_end().\r
- DECL_CONTEXT_LEXICAL,\r
- /// \brief A record that stores the set of declarations that are\r
- /// visible from a given DeclContext.\r
- ///\r
- /// The record itself stores a set of mappings, each of which\r
- /// associates a declaration name with one or more declaration\r
- /// IDs. This data is used when performing qualified name lookup\r
- /// into a DeclContext via DeclContext::lookup.\r
- DECL_CONTEXT_VISIBLE,\r
- /// \brief A LabelDecl record.\r
- DECL_LABEL,\r
- /// \brief A NamespaceDecl record.\r
- DECL_NAMESPACE,\r
- /// \brief A NamespaceAliasDecl record.\r
- DECL_NAMESPACE_ALIAS,\r
- /// \brief A UsingDecl record.\r
- DECL_USING,\r
- /// \brief A UsingShadowDecl record.\r
- DECL_USING_SHADOW,\r
- /// \brief A UsingDirecitveDecl record.\r
- DECL_USING_DIRECTIVE,\r
- /// \brief An UnresolvedUsingValueDecl record.\r
- DECL_UNRESOLVED_USING_VALUE,\r
- /// \brief An UnresolvedUsingTypenameDecl record.\r
- DECL_UNRESOLVED_USING_TYPENAME,\r
- /// \brief A LinkageSpecDecl record.\r
- DECL_LINKAGE_SPEC,\r
- /// \brief A CXXRecordDecl record.\r
- DECL_CXX_RECORD,\r
- /// \brief A CXXMethodDecl record.\r
- DECL_CXX_METHOD,\r
- /// \brief A CXXConstructorDecl record.\r
- DECL_CXX_CONSTRUCTOR,\r
- /// \brief A CXXDestructorDecl record.\r
- DECL_CXX_DESTRUCTOR,\r
- /// \brief A CXXConversionDecl record.\r
- DECL_CXX_CONVERSION,\r
- /// \brief An AccessSpecDecl record.\r
- DECL_ACCESS_SPEC,\r
-\r
- /// \brief A FriendDecl record.\r
- DECL_FRIEND,\r
- /// \brief A FriendTemplateDecl record.\r
- DECL_FRIEND_TEMPLATE,\r
- /// \brief A ClassTemplateDecl record.\r
- DECL_CLASS_TEMPLATE,\r
- /// \brief A ClassTemplateSpecializationDecl record.\r
- DECL_CLASS_TEMPLATE_SPECIALIZATION,\r
- /// \brief A ClassTemplatePartialSpecializationDecl record.\r
- DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,\r
- /// \brief A FunctionTemplateDecl record.\r
- DECL_FUNCTION_TEMPLATE,\r
- /// \brief A TemplateTypeParmDecl record.\r
- DECL_TEMPLATE_TYPE_PARM,\r
- /// \brief A NonTypeTemplateParmDecl record.\r
- DECL_NON_TYPE_TEMPLATE_PARM,\r
- /// \brief A TemplateTemplateParmDecl record.\r
- DECL_TEMPLATE_TEMPLATE_PARM,\r
- /// \brief A TypeAliasTemplateDecl record.\r
- DECL_TYPE_ALIAS_TEMPLATE,\r
- /// \brief A StaticAssertDecl record.\r
- DECL_STATIC_ASSERT,\r
- /// \brief A record containing CXXBaseSpecifiers.\r
- DECL_CXX_BASE_SPECIFIERS,\r
- /// \brief A IndirectFieldDecl record.\r
- DECL_INDIRECTFIELD,\r
- /// \brief A NonTypeTemplateParmDecl record that stores an expanded\r
- /// non-type template parameter pack.\r
- DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK,\r
- /// \brief A TemplateTemplateParmDecl record that stores an expanded\r
- /// template template parameter pack.\r
- DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK,\r
- /// \brief A ClassScopeFunctionSpecializationDecl record a class scope\r
- /// function specialization. (Microsoft extension).\r
- DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,\r
- /// \brief An ImportDecl recording a module import.\r
- DECL_IMPORT\r
- };\r
-\r
- /// \brief Record codes for each kind of statement or expression.\r
- ///\r
- /// These constants describe the records that describe statements\r
- /// or expressions. These records occur within type and declarations\r
- /// block, so they begin with record values of 100. Each constant \r
- /// describes a record for a specific statement or expression class in the\r
- /// AST.\r
- enum StmtCode {\r
- /// \brief A marker record that indicates that we are at the end\r
- /// of an expression.\r
- STMT_STOP = 100,\r
- /// \brief A NULL expression.\r
- STMT_NULL_PTR,\r
- /// \brief A reference to a previously [de]serialized Stmt record.\r
- STMT_REF_PTR,\r
- /// \brief A NullStmt record.\r
- STMT_NULL,\r
- /// \brief A CompoundStmt record.\r
- STMT_COMPOUND,\r
- /// \brief A CaseStmt record.\r
- STMT_CASE,\r
- /// \brief A DefaultStmt record.\r
- STMT_DEFAULT,\r
- /// \brief A LabelStmt record.\r
- STMT_LABEL,\r
- /// \brief An AttributedStmt record.\r
- STMT_ATTRIBUTED,\r
- /// \brief An IfStmt record.\r
- STMT_IF,\r
- /// \brief A SwitchStmt record.\r
- STMT_SWITCH,\r
- /// \brief A WhileStmt record.\r
- STMT_WHILE,\r
- /// \brief A DoStmt record.\r
- STMT_DO,\r
- /// \brief A ForStmt record.\r
- STMT_FOR,\r
- /// \brief A GotoStmt record.\r
- STMT_GOTO,\r
- /// \brief An IndirectGotoStmt record.\r
- STMT_INDIRECT_GOTO,\r
- /// \brief A ContinueStmt record.\r
- STMT_CONTINUE,\r
- /// \brief A BreakStmt record.\r
- STMT_BREAK,\r
- /// \brief A ReturnStmt record.\r
- STMT_RETURN,\r
- /// \brief A DeclStmt record.\r
- STMT_DECL,\r
- /// \brief A GCC-style AsmStmt record.\r
- STMT_GCCASM,\r
- /// \brief A MS-style AsmStmt record.\r
- STMT_MSASM,\r
- /// \brief A PredefinedExpr record.\r
- EXPR_PREDEFINED,\r
- /// \brief A DeclRefExpr record.\r
- EXPR_DECL_REF,\r
- /// \brief An IntegerLiteral record.\r
- EXPR_INTEGER_LITERAL,\r
- /// \brief A FloatingLiteral record.\r
- EXPR_FLOATING_LITERAL,\r
- /// \brief An ImaginaryLiteral record.\r
- EXPR_IMAGINARY_LITERAL,\r
- /// \brief A StringLiteral record.\r
- EXPR_STRING_LITERAL,\r
- /// \brief A CharacterLiteral record.\r
- EXPR_CHARACTER_LITERAL,\r
- /// \brief A ParenExpr record.\r
- EXPR_PAREN,\r
- /// \brief A ParenListExpr record.\r
- EXPR_PAREN_LIST,\r
- /// \brief A UnaryOperator record.\r
- EXPR_UNARY_OPERATOR,\r
- /// \brief An OffsetOfExpr record.\r
- EXPR_OFFSETOF,\r
- /// \brief A SizefAlignOfExpr record.\r
- EXPR_SIZEOF_ALIGN_OF,\r
- /// \brief An ArraySubscriptExpr record.\r
- EXPR_ARRAY_SUBSCRIPT,\r
- /// \brief A CallExpr record.\r
- EXPR_CALL,\r
- /// \brief A MemberExpr record.\r
- EXPR_MEMBER,\r
- /// \brief A BinaryOperator record.\r
- EXPR_BINARY_OPERATOR,\r
- /// \brief A CompoundAssignOperator record.\r
- EXPR_COMPOUND_ASSIGN_OPERATOR,\r
- /// \brief A ConditionOperator record.\r
- EXPR_CONDITIONAL_OPERATOR,\r
- /// \brief An ImplicitCastExpr record.\r
- EXPR_IMPLICIT_CAST,\r
- /// \brief A CStyleCastExpr record.\r
- EXPR_CSTYLE_CAST,\r
- /// \brief A CompoundLiteralExpr record.\r
- EXPR_COMPOUND_LITERAL,\r
- /// \brief An ExtVectorElementExpr record.\r
- EXPR_EXT_VECTOR_ELEMENT,\r
- /// \brief An InitListExpr record.\r
- EXPR_INIT_LIST,\r
- /// \brief A DesignatedInitExpr record.\r
- EXPR_DESIGNATED_INIT,\r
- /// \brief An ImplicitValueInitExpr record.\r
- EXPR_IMPLICIT_VALUE_INIT,\r
- /// \brief A VAArgExpr record.\r
- EXPR_VA_ARG,\r
- /// \brief An AddrLabelExpr record.\r
- EXPR_ADDR_LABEL,\r
- /// \brief A StmtExpr record.\r
- EXPR_STMT,\r
- /// \brief A ChooseExpr record.\r
- EXPR_CHOOSE,\r
- /// \brief A GNUNullExpr record.\r
- EXPR_GNU_NULL,\r
- /// \brief A ShuffleVectorExpr record.\r
- EXPR_SHUFFLE_VECTOR,\r
- /// \brief BlockExpr\r
- EXPR_BLOCK,\r
- /// \brief A GenericSelectionExpr record.\r
- EXPR_GENERIC_SELECTION,\r
- /// \brief A PseudoObjectExpr record.\r
- EXPR_PSEUDO_OBJECT,\r
- /// \brief An AtomicExpr record.\r
- EXPR_ATOMIC,\r
-\r
- // Objective-C\r
-\r
- /// \brief An ObjCStringLiteral record.\r
- EXPR_OBJC_STRING_LITERAL,\r
-\r
- EXPR_OBJC_BOXED_EXPRESSION,\r
- EXPR_OBJC_ARRAY_LITERAL,\r
- EXPR_OBJC_DICTIONARY_LITERAL,\r
-\r
- \r
- /// \brief An ObjCEncodeExpr record.\r
- EXPR_OBJC_ENCODE,\r
- /// \brief An ObjCSelectorExpr record.\r
- EXPR_OBJC_SELECTOR_EXPR,\r
- /// \brief An ObjCProtocolExpr record.\r
- EXPR_OBJC_PROTOCOL_EXPR,\r
- /// \brief An ObjCIvarRefExpr record.\r
- EXPR_OBJC_IVAR_REF_EXPR,\r
- /// \brief An ObjCPropertyRefExpr record.\r
- EXPR_OBJC_PROPERTY_REF_EXPR,\r
- /// \brief An ObjCSubscriptRefExpr record.\r
- EXPR_OBJC_SUBSCRIPT_REF_EXPR,\r
- /// \brief UNUSED\r
- EXPR_OBJC_KVC_REF_EXPR,\r
- /// \brief An ObjCMessageExpr record.\r
- EXPR_OBJC_MESSAGE_EXPR,\r
- /// \brief An ObjCIsa Expr record.\r
- EXPR_OBJC_ISA,\r
- /// \brief An ObjCIndirectCopyRestoreExpr record.\r
- EXPR_OBJC_INDIRECT_COPY_RESTORE,\r
-\r
- /// \brief An ObjCForCollectionStmt record.\r
- STMT_OBJC_FOR_COLLECTION,\r
- /// \brief An ObjCAtCatchStmt record.\r
- STMT_OBJC_CATCH,\r
- /// \brief An ObjCAtFinallyStmt record.\r
- STMT_OBJC_FINALLY,\r
- /// \brief An ObjCAtTryStmt record.\r
- STMT_OBJC_AT_TRY,\r
- /// \brief An ObjCAtSynchronizedStmt record.\r
- STMT_OBJC_AT_SYNCHRONIZED,\r
- /// \brief An ObjCAtThrowStmt record.\r
- STMT_OBJC_AT_THROW,\r
- /// \brief An ObjCAutoreleasePoolStmt record.\r
- STMT_OBJC_AUTORELEASE_POOL,\r
- /// \brief A ObjCBoolLiteralExpr record.\r
- EXPR_OBJC_BOOL_LITERAL,\r
-\r
- // C++\r
- \r
- /// \brief A CXXCatchStmt record.\r
- STMT_CXX_CATCH,\r
- /// \brief A CXXTryStmt record.\r
- STMT_CXX_TRY,\r
- /// \brief A CXXForRangeStmt record.\r
- STMT_CXX_FOR_RANGE,\r
-\r
- /// \brief A CXXOperatorCallExpr record.\r
- EXPR_CXX_OPERATOR_CALL,\r
- /// \brief A CXXMemberCallExpr record.\r
- EXPR_CXX_MEMBER_CALL,\r
- /// \brief A CXXConstructExpr record.\r
- EXPR_CXX_CONSTRUCT,\r
- /// \brief A CXXTemporaryObjectExpr record.\r
- EXPR_CXX_TEMPORARY_OBJECT,\r
- /// \brief A CXXStaticCastExpr record.\r
- EXPR_CXX_STATIC_CAST,\r
- /// \brief A CXXDynamicCastExpr record.\r
- EXPR_CXX_DYNAMIC_CAST,\r
- /// \brief A CXXReinterpretCastExpr record.\r
- EXPR_CXX_REINTERPRET_CAST,\r
- /// \brief A CXXConstCastExpr record.\r
- EXPR_CXX_CONST_CAST,\r
- /// \brief A CXXFunctionalCastExpr record.\r
- EXPR_CXX_FUNCTIONAL_CAST,\r
- /// \brief A UserDefinedLiteral record.\r
- EXPR_USER_DEFINED_LITERAL,\r
- /// \brief A CXXBoolLiteralExpr record.\r
- EXPR_CXX_BOOL_LITERAL,\r
- EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr\r
- EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr).\r
- EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type).\r
- EXPR_CXX_THIS, // CXXThisExpr\r
- EXPR_CXX_THROW, // CXXThrowExpr\r
- EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr\r
- EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr\r
-\r
- EXPR_CXX_SCALAR_VALUE_INIT, // CXXScalarValueInitExpr\r
- EXPR_CXX_NEW, // CXXNewExpr\r
- EXPR_CXX_DELETE, // CXXDeleteExpr\r
- EXPR_CXX_PSEUDO_DESTRUCTOR, // CXXPseudoDestructorExpr\r
- \r
- EXPR_EXPR_WITH_CLEANUPS, // ExprWithCleanups\r
- \r
- EXPR_CXX_DEPENDENT_SCOPE_MEMBER, // CXXDependentScopeMemberExpr\r
- EXPR_CXX_DEPENDENT_SCOPE_DECL_REF, // DependentScopeDeclRefExpr\r
- EXPR_CXX_UNRESOLVED_CONSTRUCT, // CXXUnresolvedConstructExpr\r
- EXPR_CXX_UNRESOLVED_MEMBER, // UnresolvedMemberExpr\r
- EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr\r
-\r
- EXPR_CXX_UNARY_TYPE_TRAIT, // UnaryTypeTraitExpr\r
- EXPR_CXX_EXPRESSION_TRAIT, // ExpressionTraitExpr\r
- EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr\r
-\r
- EXPR_OPAQUE_VALUE, // OpaqueValueExpr\r
- EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator\r
- EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr\r
- EXPR_TYPE_TRAIT, // TypeTraitExpr\r
- EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr\r
- \r
- EXPR_PACK_EXPANSION, // PackExpansionExpr\r
- EXPR_SIZEOF_PACK, // SizeOfPackExpr\r
- EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, // SubstNonTypeTemplateParmExpr\r
- EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr\r
- EXPR_FUNCTION_PARM_PACK, // FunctionParmPackExpr\r
- EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr\r
- \r
- // CUDA\r
- EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr \r
-\r
- // OpenCL\r
- EXPR_ASTYPE, // AsTypeExpr\r
-\r
- // Microsoft\r
- EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr).\r
- EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type).\r
- STMT_SEH_EXCEPT, // SEHExceptStmt\r
- STMT_SEH_FINALLY, // SEHFinallyStmt\r
- STMT_SEH_TRY, // SEHTryStmt\r
- \r
- // ARC\r
- EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr\r
- \r
- STMT_MS_DEPENDENT_EXISTS, // MSDependentExistsStmt\r
- EXPR_LAMBDA // LambdaExpr\r
- };\r
-\r
- /// \brief The kinds of designators that can occur in a\r
- /// DesignatedInitExpr.\r
- enum DesignatorTypes {\r
- /// \brief Field designator where only the field name is known.\r
- DESIG_FIELD_NAME = 0,\r
- /// \brief Field designator where the field has been resolved to\r
- /// a declaration.\r
- DESIG_FIELD_DECL = 1,\r
- /// \brief Array designator.\r
- DESIG_ARRAY = 2,\r
- /// \brief GNU array range designator.\r
- DESIG_ARRAY_RANGE = 3\r
- };\r
-\r
- /// \brief The different kinds of data that can occur in a\r
- /// CtorInitializer.\r
- enum CtorInitializerType {\r
- CTOR_INITIALIZER_BASE,\r
- CTOR_INITIALIZER_DELEGATING,\r
- CTOR_INITIALIZER_MEMBER,\r
- CTOR_INITIALIZER_INDIRECT_MEMBER\r
- };\r
-\r
- /// \brief Describes the redeclarations of a declaration.\r
- struct LocalRedeclarationsInfo {\r
- DeclID FirstID; // The ID of the first declaration\r
- unsigned Offset; // Offset into the array of redeclaration chains.\r
- \r
- friend bool operator<(const LocalRedeclarationsInfo &X,\r
- const LocalRedeclarationsInfo &Y) {\r
- return X.FirstID < Y.FirstID;\r
- }\r
- \r
- friend bool operator>(const LocalRedeclarationsInfo &X,\r
- const LocalRedeclarationsInfo &Y) {\r
- return X.FirstID > Y.FirstID;\r
- }\r
- \r
- friend bool operator<=(const LocalRedeclarationsInfo &X,\r
- const LocalRedeclarationsInfo &Y) {\r
- return X.FirstID <= Y.FirstID;\r
- }\r
- \r
- friend bool operator>=(const LocalRedeclarationsInfo &X,\r
- const LocalRedeclarationsInfo &Y) {\r
- return X.FirstID >= Y.FirstID;\r
- }\r
- };\r
-\r
- /// \brief Describes the categories of an Objective-C class.\r
- struct ObjCCategoriesInfo {\r
- DeclID DefinitionID; // The ID of the definition\r
- unsigned Offset; // Offset into the array of category lists.\r
- \r
- friend bool operator<(const ObjCCategoriesInfo &X,\r
- const ObjCCategoriesInfo &Y) {\r
- return X.DefinitionID < Y.DefinitionID;\r
- }\r
- \r
- friend bool operator>(const ObjCCategoriesInfo &X,\r
- const ObjCCategoriesInfo &Y) {\r
- return X.DefinitionID > Y.DefinitionID;\r
- }\r
- \r
- friend bool operator<=(const ObjCCategoriesInfo &X,\r
- const ObjCCategoriesInfo &Y) {\r
- return X.DefinitionID <= Y.DefinitionID;\r
- }\r
- \r
- friend bool operator>=(const ObjCCategoriesInfo &X,\r
- const ObjCCategoriesInfo &Y) {\r
- return X.DefinitionID >= Y.DefinitionID;\r
- }\r
- };\r
-\r
- /// @}\r
- }\r
-} // end namespace clang\r
-\r
-#endif\r
+//===- 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
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() ?
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:
-//===--- ItaniumMangle.cpp - Itanium C++ Name Mangling ----------*- C++ -*-===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// Implements C++ name mangling according to the Itanium C++ ABI,\r
-// which is used in GCC 3.2 and newer (and many compilers that are\r
-// ABI-compatible with GCC):\r
-//\r
-// http://www.codesourcery.com/public/cxx-abi/abi.html\r
-//\r
-//===----------------------------------------------------------------------===//\r
-#include "clang/AST/Mangle.h"\r
-#include "clang/AST/ASTContext.h"\r
-#include "clang/AST/Attr.h"\r
-#include "clang/AST/Decl.h"\r
-#include "clang/AST/DeclCXX.h"\r
-#include "clang/AST/DeclObjC.h"\r
-#include "clang/AST/DeclTemplate.h"\r
-#include "clang/AST/ExprCXX.h"\r
-#include "clang/AST/ExprObjC.h"\r
-#include "clang/AST/TypeLoc.h"\r
-#include "clang/Basic/ABI.h"\r
-#include "clang/Basic/SourceManager.h"\r
-#include "clang/Basic/TargetInfo.h"\r
-#include "llvm/ADT/StringExtras.h"\r
-#include "llvm/Support/ErrorHandling.h"\r
-#include "llvm/Support/raw_ostream.h"\r
-\r
-#define MANGLE_CHECKER 0\r
-\r
-#if MANGLE_CHECKER\r
-#include <cxxabi.h>\r
-#endif\r
-\r
-using namespace clang;\r
-\r
-namespace {\r
-\r
-/// \brief Retrieve the declaration context that should be used when mangling \r
-/// the given declaration.\r
-static const DeclContext *getEffectiveDeclContext(const Decl *D) {\r
- // The ABI assumes that lambda closure types that occur within \r
- // default arguments live in the context of the function. However, due to\r
- // the way in which Clang parses and creates function declarations, this is\r
- // not the case: the lambda closure type ends up living in the context \r
- // where the function itself resides, because the function declaration itself\r
- // had not yet been created. Fix the context here.\r
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {\r
- if (RD->isLambda())\r
- if (ParmVarDecl *ContextParam\r
- = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))\r
- return ContextParam->getDeclContext();\r
- }\r
- \r
- return D->getDeclContext();\r
-}\r
-\r
-static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {\r
- return getEffectiveDeclContext(cast<Decl>(DC));\r
-}\r
- \r
-static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) {\r
- const DeclContext *DC = dyn_cast<DeclContext>(ND);\r
- if (!DC)\r
- DC = getEffectiveDeclContext(ND);\r
- while (!DC->isNamespace() && !DC->isTranslationUnit()) {\r
- const DeclContext *Parent = getEffectiveDeclContext(cast<Decl>(DC));\r
- if (isa<FunctionDecl>(Parent))\r
- return dyn_cast<CXXRecordDecl>(DC);\r
- DC = Parent;\r
- }\r
- return 0;\r
-}\r
-\r
-static const FunctionDecl *getStructor(const FunctionDecl *fn) {\r
- if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())\r
- return ftd->getTemplatedDecl();\r
-\r
- return fn;\r
-}\r
-\r
-static const NamedDecl *getStructor(const NamedDecl *decl) {\r
- const FunctionDecl *fn = dyn_cast_or_null<FunctionDecl>(decl);\r
- return (fn ? getStructor(fn) : decl);\r
-}\r
- \r
-static const unsigned UnknownArity = ~0U;\r
-\r
-class ItaniumMangleContext : public MangleContext {\r
- llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds;\r
- unsigned Discriminator;\r
- llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;\r
- \r
-public:\r
- explicit ItaniumMangleContext(ASTContext &Context,\r
- DiagnosticsEngine &Diags)\r
- : MangleContext(Context, Diags) { }\r
-\r
- uint64_t getAnonymousStructId(const TagDecl *TD) {\r
- std::pair<llvm::DenseMap<const TagDecl *,\r
- uint64_t>::iterator, bool> Result =\r
- AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size()));\r
- return Result.first->second;\r
- }\r
-\r
- void startNewFunction() {\r
- MangleContext::startNewFunction();\r
- mangleInitDiscriminator();\r
- }\r
-\r
- /// @name Mangler Entry Points\r
- /// @{\r
-\r
- bool shouldMangleDeclName(const NamedDecl *D);\r
- void mangleName(const NamedDecl *D, raw_ostream &);\r
- void mangleThunk(const CXXMethodDecl *MD,\r
- const ThunkInfo &Thunk,\r
- raw_ostream &);\r
- void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,\r
- const ThisAdjustment &ThisAdjustment,\r
- raw_ostream &);\r
- void mangleReferenceTemporary(const VarDecl *D,\r
- raw_ostream &);\r
- void mangleCXXVTable(const CXXRecordDecl *RD,\r
- raw_ostream &);\r
- void mangleCXXVTT(const CXXRecordDecl *RD,\r
- raw_ostream &);\r
- void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,\r
- const CXXRecordDecl *Type,\r
- raw_ostream &);\r
- void mangleCXXRTTI(QualType T, raw_ostream &);\r
- void mangleCXXRTTIName(QualType T, raw_ostream &);\r
- void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,\r
- raw_ostream &);\r
- void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,\r
- raw_ostream &);\r
-\r
- void mangleItaniumGuardVariable(const VarDecl *D, raw_ostream &);\r
-\r
- void mangleInitDiscriminator() {\r
- Discriminator = 0;\r
- }\r
-\r
- bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {\r
- // Lambda closure types with external linkage (indicated by a \r
- // non-zero lambda mangling number) have their own numbering scheme, so\r
- // they do not need a discriminator.\r
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(ND))\r
- if (RD->isLambda() && RD->getLambdaManglingNumber() > 0)\r
- return false;\r
- \r
- unsigned &discriminator = Uniquifier[ND];\r
- if (!discriminator)\r
- discriminator = ++Discriminator;\r
- if (discriminator == 1)\r
- return false;\r
- disc = discriminator-2;\r
- return true;\r
- }\r
- /// @}\r
-};\r
-\r
-/// CXXNameMangler - Manage the mangling of a single name.\r
-class CXXNameMangler {\r
- ItaniumMangleContext &Context;\r
- raw_ostream &Out;\r
-\r
- /// The "structor" is the top-level declaration being mangled, if\r
- /// that's not a template specialization; otherwise it's the pattern\r
- /// for that specialization.\r
- const NamedDecl *Structor;\r
- unsigned StructorType;\r
-\r
- /// SeqID - The next subsitution sequence number.\r
- unsigned SeqID;\r
-\r
- class FunctionTypeDepthState {\r
- unsigned Bits;\r
-\r
- enum { InResultTypeMask = 1 };\r
-\r
- public:\r
- FunctionTypeDepthState() : Bits(0) {}\r
-\r
- /// The number of function types we're inside.\r
- unsigned getDepth() const {\r
- return Bits >> 1;\r
- }\r
-\r
- /// True if we're in the return type of the innermost function type.\r
- bool isInResultType() const {\r
- return Bits & InResultTypeMask;\r
- }\r
-\r
- FunctionTypeDepthState push() {\r
- FunctionTypeDepthState tmp = *this;\r
- Bits = (Bits & ~InResultTypeMask) + 2;\r
- return tmp;\r
- }\r
-\r
- void enterResultType() {\r
- Bits |= InResultTypeMask;\r
- }\r
-\r
- void leaveResultType() {\r
- Bits &= ~InResultTypeMask;\r
- }\r
-\r
- void pop(FunctionTypeDepthState saved) {\r
- assert(getDepth() == saved.getDepth() + 1);\r
- Bits = saved.Bits;\r
- }\r
-\r
- } FunctionTypeDepth;\r
-\r
- llvm::DenseMap<uintptr_t, unsigned> Substitutions;\r
-\r
- ASTContext &getASTContext() const { return Context.getASTContext(); }\r
-\r
-public:\r
- CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_,\r
- const NamedDecl *D = 0)\r
- : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0),\r
- SeqID(0) {\r
- // These can't be mangled without a ctor type or dtor type.\r
- assert(!D || (!isa<CXXDestructorDecl>(D) &&\r
- !isa<CXXConstructorDecl>(D)));\r
- }\r
- CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_,\r
- const CXXConstructorDecl *D, CXXCtorType Type)\r
- : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),\r
- SeqID(0) { }\r
- CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_,\r
- const CXXDestructorDecl *D, CXXDtorType Type)\r
- : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),\r
- SeqID(0) { }\r
-\r
-#if MANGLE_CHECKER\r
- ~CXXNameMangler() {\r
- if (Out.str()[0] == '\01')\r
- return;\r
-\r
- int status = 0;\r
- char *result = abi::__cxa_demangle(Out.str().str().c_str(), 0, 0, &status);\r
- assert(status == 0 && "Could not demangle mangled name!");\r
- free(result);\r
- }\r
-#endif\r
- raw_ostream &getStream() { return Out; }\r
-\r
- void mangle(const NamedDecl *D, StringRef Prefix = "_Z");\r
- void mangleCallOffset(int64_t NonVirtual, int64_t Virtual);\r
- void mangleNumber(const llvm::APSInt &I);\r
- void mangleNumber(int64_t Number);\r
- void mangleFloat(const llvm::APFloat &F);\r
- void mangleFunctionEncoding(const FunctionDecl *FD);\r
- void mangleName(const NamedDecl *ND);\r
- void mangleType(QualType T);\r
- void mangleNameOrStandardSubstitution(const NamedDecl *ND);\r
- \r
-private:\r
- bool mangleSubstitution(const NamedDecl *ND);\r
- bool mangleSubstitution(QualType T);\r
- bool mangleSubstitution(TemplateName Template);\r
- bool mangleSubstitution(uintptr_t Ptr);\r
-\r
- void mangleExistingSubstitution(QualType type);\r
- void mangleExistingSubstitution(TemplateName name);\r
-\r
- bool mangleStandardSubstitution(const NamedDecl *ND);\r
-\r
- void addSubstitution(const NamedDecl *ND) {\r
- ND = cast<NamedDecl>(ND->getCanonicalDecl());\r
-\r
- addSubstitution(reinterpret_cast<uintptr_t>(ND));\r
- }\r
- void addSubstitution(QualType T);\r
- void addSubstitution(TemplateName Template);\r
- void addSubstitution(uintptr_t Ptr);\r
-\r
- void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,\r
- NamedDecl *firstQualifierLookup,\r
- bool recursive = false);\r
- void mangleUnresolvedName(NestedNameSpecifier *qualifier,\r
- NamedDecl *firstQualifierLookup,\r
- DeclarationName name,\r
- unsigned KnownArity = UnknownArity);\r
-\r
- void mangleName(const TemplateDecl *TD,\r
- const TemplateArgument *TemplateArgs,\r
- unsigned NumTemplateArgs);\r
- void mangleUnqualifiedName(const NamedDecl *ND) {\r
- mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity);\r
- }\r
- void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name,\r
- unsigned KnownArity);\r
- void mangleUnscopedName(const NamedDecl *ND);\r
- void mangleUnscopedTemplateName(const TemplateDecl *ND);\r
- void mangleUnscopedTemplateName(TemplateName);\r
- void mangleSourceName(const IdentifierInfo *II);\r
- void mangleLocalName(const NamedDecl *ND);\r
- void mangleLambda(const CXXRecordDecl *Lambda);\r
- void mangleNestedName(const NamedDecl *ND, const DeclContext *DC,\r
- bool NoFunction=false);\r
- void mangleNestedName(const TemplateDecl *TD,\r
- const TemplateArgument *TemplateArgs,\r
- unsigned NumTemplateArgs);\r
- void manglePrefix(NestedNameSpecifier *qualifier);\r
- void manglePrefix(const DeclContext *DC, bool NoFunction=false);\r
- void manglePrefix(QualType type);\r
- void mangleTemplatePrefix(const TemplateDecl *ND);\r
- void mangleTemplatePrefix(TemplateName Template);\r
- void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);\r
- void mangleQualifiers(Qualifiers Quals);\r
- void mangleRefQualifier(RefQualifierKind RefQualifier);\r
-\r
- void mangleObjCMethodName(const ObjCMethodDecl *MD);\r
-\r
- // Declare manglers for every type class.\r
-#define ABSTRACT_TYPE(CLASS, PARENT)\r
-#define NON_CANONICAL_TYPE(CLASS, PARENT)\r
-#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T);\r
-#include "clang/AST/TypeNodes.def"\r
-\r
- void mangleType(const TagType*);\r
- void mangleType(TemplateName);\r
- void mangleBareFunctionType(const FunctionType *T,\r
- bool MangleReturnType);\r
- void mangleNeonVectorType(const VectorType *T);\r
-\r
- void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);\r
- void mangleMemberExpr(const Expr *base, bool isArrow,\r
- NestedNameSpecifier *qualifier,\r
- NamedDecl *firstQualifierLookup,\r
- DeclarationName name,\r
- unsigned knownArity);\r
- void mangleExpression(const Expr *E, unsigned Arity = UnknownArity);\r
- void mangleCXXCtorType(CXXCtorType T);\r
- void mangleCXXDtorType(CXXDtorType T);\r
-\r
- void mangleTemplateArgs(const ASTTemplateArgumentListInfo &TemplateArgs);\r
- void mangleTemplateArgs(const TemplateArgument *TemplateArgs,\r
- unsigned NumTemplateArgs);\r
- void mangleTemplateArgs(const TemplateArgumentList &AL);\r
- void mangleTemplateArg(TemplateArgument A);\r
-\r
- void mangleTemplateParameter(unsigned Index);\r
-\r
- void mangleFunctionParam(const ParmVarDecl *parm);\r
-};\r
-\r
-}\r
-\r
-static bool isInCLinkageSpecification(const Decl *D) {\r
- D = D->getCanonicalDecl();\r
- for (const DeclContext *DC = getEffectiveDeclContext(D);\r
- !DC->isTranslationUnit(); DC = getEffectiveParentContext(DC)) {\r
- if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))\r
- return Linkage->getLanguage() == LinkageSpecDecl::lang_c;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) {\r
- // In C, functions with no attributes never need to be mangled. Fastpath them.\r
- if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())\r
- return false;\r
-\r
- // Any decl can be declared with __asm("foo") on it, and this takes precedence\r
- // over all other naming in the .o file.\r
- if (D->hasAttr<AsmLabelAttr>())\r
- return true;\r
-\r
- // Clang's "overloadable" attribute extension to C/C++ implies name mangling\r
- // (always) as does passing a C++ member function and a function\r
- // whose name is not a simple identifier.\r
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);\r
- if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) ||\r
- !FD->getDeclName().isIdentifier()))\r
- return true;\r
-\r
- // Otherwise, no mangling is done outside C++ mode.\r
- if (!getASTContext().getLangOpts().CPlusPlus)\r
- return false;\r
-\r
- // Variables at global scope with non-internal linkage are not mangled\r
- if (!FD) {\r
- const DeclContext *DC = getEffectiveDeclContext(D);\r
- // Check for extern variable declared locally.\r
- if (DC->isFunctionOrMethod() && D->hasLinkage())\r
- while (!DC->isNamespace() && !DC->isTranslationUnit())\r
- DC = getEffectiveParentContext(DC);\r
- if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage)\r
- return false;\r
- }\r
-\r
- // Class members are always mangled.\r
- if (getEffectiveDeclContext(D)->isRecord())\r
- return true;\r
-\r
- // C functions and "main" are not mangled.\r
- if ((FD && FD->isMain()) || isInCLinkageSpecification(D))\r
- return false;\r
-\r
- return true;\r
-}\r
-\r
-void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {\r
- // Any decl can be declared with __asm("foo") on it, and this takes precedence\r
- // over all other naming in the .o file.\r
- if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {\r
- // If we have an asm name, then we use it as the mangling.\r
-\r
- // Adding the prefix can cause problems when one file has a "foo" and\r
- // another has a "\01foo". That is known to happen on ELF with the\r
- // tricks normally used for producing aliases (PR9177). Fortunately the\r
- // llvm mangler on ELF is a nop, so we can just avoid adding the \01\r
- // marker. We also avoid adding the marker if this is an alias for an\r
- // LLVM intrinsic.\r
- StringRef UserLabelPrefix =\r
- getASTContext().getTargetInfo().getUserLabelPrefix();\r
- if (!UserLabelPrefix.empty() && !ALA->getLabel().startswith("llvm."))\r
- Out << '\01'; // LLVM IR Marker for __asm("foo")\r
-\r
- Out << ALA->getLabel();\r
- return;\r
- }\r
-\r
- // <mangled-name> ::= _Z <encoding>\r
- // ::= <data name>\r
- // ::= <special-name>\r
- Out << Prefix;\r
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))\r
- mangleFunctionEncoding(FD);\r
- else if (const VarDecl *VD = dyn_cast<VarDecl>(D))\r
- mangleName(VD);\r
- else\r
- mangleName(cast<FieldDecl>(D));\r
-}\r
-\r
-void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {\r
- // <encoding> ::= <function name> <bare-function-type>\r
- mangleName(FD);\r
-\r
- // Don't mangle in the type if this isn't a decl we should typically mangle.\r
- if (!Context.shouldMangleDeclName(FD))\r
- return;\r
-\r
- // Whether the mangling of a function type includes the return type depends on\r
- // the context and the nature of the function. The rules for deciding whether\r
- // the return type is included are:\r
- //\r
- // 1. Template functions (names or types) have return types encoded, with\r
- // the exceptions listed below.\r
- // 2. Function types not appearing as part of a function name mangling,\r
- // e.g. parameters, pointer types, etc., have return type encoded, with the\r
- // exceptions listed below.\r
- // 3. Non-template function names do not have return types encoded.\r
- //\r
- // The exceptions mentioned in (1) and (2) above, for which the return type is\r
- // never included, are\r
- // 1. Constructors.\r
- // 2. Destructors.\r
- // 3. Conversion operator functions, e.g. operator int.\r
- bool MangleReturnType = false;\r
- if (FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate()) {\r
- if (!(isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) ||\r
- isa<CXXConversionDecl>(FD)))\r
- MangleReturnType = true;\r
-\r
- // Mangle the type of the primary template.\r
- FD = PrimaryTemplate->getTemplatedDecl();\r
- }\r
-\r
- mangleBareFunctionType(FD->getType()->getAs<FunctionType>(), \r
- MangleReturnType);\r
-}\r
-\r
-static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {\r
- while (isa<LinkageSpecDecl>(DC)) {\r
- DC = getEffectiveParentContext(DC);\r
- }\r
-\r
- return DC;\r
-}\r
-\r
-/// isStd - Return whether a given namespace is the 'std' namespace.\r
-static bool isStd(const NamespaceDecl *NS) {\r
- if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS))\r
- ->isTranslationUnit())\r
- return false;\r
- \r
- const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier();\r
- return II && II->isStr("std");\r
-}\r
-\r
-// isStdNamespace - Return whether a given decl context is a toplevel 'std'\r
-// namespace.\r
-static bool isStdNamespace(const DeclContext *DC) {\r
- if (!DC->isNamespace())\r
- return false;\r
-\r
- return isStd(cast<NamespaceDecl>(DC));\r
-}\r
-\r
-static const TemplateDecl *\r
-isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {\r
- // Check if we have a function template.\r
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){\r
- if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {\r
- TemplateArgs = FD->getTemplateSpecializationArgs();\r
- return TD;\r
- }\r
- }\r
-\r
- // Check if we have a class template.\r
- if (const ClassTemplateSpecializationDecl *Spec =\r
- dyn_cast<ClassTemplateSpecializationDecl>(ND)) {\r
- TemplateArgs = &Spec->getTemplateArgs();\r
- return Spec->getSpecializedTemplate();\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-static bool isLambda(const NamedDecl *ND) {\r
- const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND);\r
- if (!Record)\r
- return false;\r
- \r
- return Record->isLambda();\r
-}\r
-\r
-void CXXNameMangler::mangleName(const NamedDecl *ND) {\r
- // <name> ::= <nested-name>\r
- // ::= <unscoped-name>\r
- // ::= <unscoped-template-name> <template-args>\r
- // ::= <local-name>\r
- //\r
- const DeclContext *DC = getEffectiveDeclContext(ND);\r
-\r
- // If this is an extern variable declared locally, the relevant DeclContext\r
- // is that of the containing namespace, or the translation unit.\r
- // FIXME: This is a hack; extern variables declared locally should have\r
- // a proper semantic declaration context!\r
- if (isa<FunctionDecl>(DC) && ND->hasLinkage() && !isLambda(ND))\r
- while (!DC->isNamespace() && !DC->isTranslationUnit())\r
- DC = getEffectiveParentContext(DC);\r
- else if (GetLocalClassDecl(ND)) {\r
- mangleLocalName(ND);\r
- return;\r
- }\r
-\r
- DC = IgnoreLinkageSpecDecls(DC);\r
-\r
- if (DC->isTranslationUnit() || isStdNamespace(DC)) {\r
- // Check if we have a template.\r
- const TemplateArgumentList *TemplateArgs = 0;\r
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {\r
- mangleUnscopedTemplateName(TD);\r
- mangleTemplateArgs(*TemplateArgs);\r
- return;\r
- }\r
-\r
- mangleUnscopedName(ND);\r
- return;\r
- }\r
-\r
- if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) {\r
- mangleLocalName(ND);\r
- return;\r
- }\r
-\r
- mangleNestedName(ND, DC);\r
-}\r
-void CXXNameMangler::mangleName(const TemplateDecl *TD,\r
- const TemplateArgument *TemplateArgs,\r
- unsigned NumTemplateArgs) {\r
- const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD));\r
-\r
- if (DC->isTranslationUnit() || isStdNamespace(DC)) {\r
- mangleUnscopedTemplateName(TD);\r
- mangleTemplateArgs(TemplateArgs, NumTemplateArgs);\r
- } else {\r
- mangleNestedName(TD, TemplateArgs, NumTemplateArgs);\r
- }\r
-}\r
-\r
-void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) {\r
- // <unscoped-name> ::= <unqualified-name>\r
- // ::= St <unqualified-name> # ::std::\r
-\r
- if (isStdNamespace(IgnoreLinkageSpecDecls(getEffectiveDeclContext(ND))))\r
- Out << "St";\r
-\r
- mangleUnqualifiedName(ND);\r
-}\r
-\r
-void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) {\r
- // <unscoped-template-name> ::= <unscoped-name>\r
- // ::= <substitution>\r
- if (mangleSubstitution(ND))\r
- return;\r
-\r
- // <template-template-param> ::= <template-param>\r
- if (const TemplateTemplateParmDecl *TTP\r
- = dyn_cast<TemplateTemplateParmDecl>(ND)) {\r
- mangleTemplateParameter(TTP->getIndex());\r
- return;\r
- }\r
-\r
- mangleUnscopedName(ND->getTemplatedDecl());\r
- addSubstitution(ND);\r
-}\r
-\r
-void CXXNameMangler::mangleUnscopedTemplateName(TemplateName Template) {\r
- // <unscoped-template-name> ::= <unscoped-name>\r
- // ::= <substitution>\r
- if (TemplateDecl *TD = Template.getAsTemplateDecl())\r
- return mangleUnscopedTemplateName(TD);\r
- \r
- if (mangleSubstitution(Template))\r
- return;\r
-\r
- DependentTemplateName *Dependent = Template.getAsDependentTemplateName();\r
- assert(Dependent && "Not a dependent template name?");\r
- if (const IdentifierInfo *Id = Dependent->getIdentifier())\r
- mangleSourceName(Id);\r
- else\r
- mangleOperatorName(Dependent->getOperator(), UnknownArity);\r
- \r
- addSubstitution(Template);\r
-}\r
-\r
-void CXXNameMangler::mangleFloat(const llvm::APFloat &f) {\r
- // ABI:\r
- // Floating-point literals are encoded using a fixed-length\r
- // lowercase hexadecimal string corresponding to the internal\r
- // representation (IEEE on Itanium), high-order bytes first,\r
- // without leading zeroes. For example: "Lf bf800000 E" is -1.0f\r
- // on Itanium.\r
- // The 'without leading zeroes' thing seems to be an editorial\r
- // mistake; see the discussion on cxx-abi-dev beginning on\r
- // 2012-01-16.\r
-\r
- // Our requirements here are just barely weird enough to justify\r
- // using a custom algorithm instead of post-processing APInt::toString().\r
-\r
- llvm::APInt valueBits = f.bitcastToAPInt();\r
- unsigned numCharacters = (valueBits.getBitWidth() + 3) / 4;\r
- assert(numCharacters != 0);\r
-\r
- // Allocate a buffer of the right number of characters.\r
- llvm::SmallVector<char, 20> buffer;\r
- buffer.set_size(numCharacters);\r
-\r
- // Fill the buffer left-to-right.\r
- for (unsigned stringIndex = 0; stringIndex != numCharacters; ++stringIndex) {\r
- // The bit-index of the next hex digit.\r
- unsigned digitBitIndex = 4 * (numCharacters - stringIndex - 1);\r
-\r
- // Project out 4 bits starting at 'digitIndex'.\r
- llvm::integerPart hexDigit\r
- = valueBits.getRawData()[digitBitIndex / llvm::integerPartWidth];\r
- hexDigit >>= (digitBitIndex % llvm::integerPartWidth);\r
- hexDigit &= 0xF;\r
-\r
- // Map that over to a lowercase hex digit.\r
- static const char charForHex[16] = {\r
- '0', '1', '2', '3', '4', '5', '6', '7',\r
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'\r
- };\r
- buffer[stringIndex] = charForHex[hexDigit];\r
- }\r
-\r
- Out.write(buffer.data(), numCharacters);\r
-}\r
-\r
-void CXXNameMangler::mangleNumber(const llvm::APSInt &Value) {\r
- if (Value.isSigned() && Value.isNegative()) {\r
- Out << 'n';\r
- Value.abs().print(Out, /*signed*/ false);\r
- } else {\r
- Value.print(Out, /*signed*/ false);\r
- }\r
-}\r
-\r
-void CXXNameMangler::mangleNumber(int64_t Number) {\r
- // <number> ::= [n] <non-negative decimal integer>\r
- if (Number < 0) {\r
- Out << 'n';\r
- Number = -Number;\r
- }\r
-\r
- Out << Number;\r
-}\r
-\r
-void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) {\r
- // <call-offset> ::= h <nv-offset> _\r
- // ::= v <v-offset> _\r
- // <nv-offset> ::= <offset number> # non-virtual base override\r
- // <v-offset> ::= <offset number> _ <virtual offset number>\r
- // # virtual base override, with vcall offset\r
- if (!Virtual) {\r
- Out << 'h';\r
- mangleNumber(NonVirtual);\r
- Out << '_';\r
- return;\r
- }\r
-\r
- Out << 'v';\r
- mangleNumber(NonVirtual);\r
- Out << '_';\r
- mangleNumber(Virtual);\r
- Out << '_';\r
-}\r
-\r
-void CXXNameMangler::manglePrefix(QualType type) {\r
- if (const TemplateSpecializationType *TST =\r
- type->getAs<TemplateSpecializationType>()) {\r
- if (!mangleSubstitution(QualType(TST, 0))) {\r
- mangleTemplatePrefix(TST->getTemplateName());\r
- \r
- // FIXME: GCC does not appear to mangle the template arguments when\r
- // the template in question is a dependent template name. Should we\r
- // emulate that badness?\r
- mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());\r
- addSubstitution(QualType(TST, 0));\r
- }\r
- } else if (const DependentTemplateSpecializationType *DTST\r
- = type->getAs<DependentTemplateSpecializationType>()) {\r
- TemplateName Template\r
- = getASTContext().getDependentTemplateName(DTST->getQualifier(), \r
- DTST->getIdentifier());\r
- mangleTemplatePrefix(Template);\r
-\r
- // FIXME: GCC does not appear to mangle the template arguments when\r
- // the template in question is a dependent template name. Should we\r
- // emulate that badness?\r
- mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());\r
- } else {\r
- // We use the QualType mangle type variant here because it handles\r
- // substitutions.\r
- mangleType(type);\r
- }\r
-}\r
-\r
-/// Mangle everything prior to the base-unresolved-name in an unresolved-name.\r
-///\r
-/// \param firstQualifierLookup - the entity found by unqualified lookup\r
-/// for the first name in the qualifier, if this is for a member expression\r
-/// \param recursive - true if this is being called recursively,\r
-/// i.e. if there is more prefix "to the right".\r
-void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,\r
- NamedDecl *firstQualifierLookup,\r
- bool recursive) {\r
-\r
- // x, ::x\r
- // <unresolved-name> ::= [gs] <base-unresolved-name>\r
-\r
- // T::x / decltype(p)::x\r
- // <unresolved-name> ::= sr <unresolved-type> <base-unresolved-name>\r
-\r
- // T::N::x /decltype(p)::N::x\r
- // <unresolved-name> ::= srN <unresolved-type> <unresolved-qualifier-level>+ E\r
- // <base-unresolved-name>\r
-\r
- // A::x, N::y, A<T>::z; "gs" means leading "::"\r
- // <unresolved-name> ::= [gs] sr <unresolved-qualifier-level>+ E\r
- // <base-unresolved-name>\r
-\r
- switch (qualifier->getKind()) {\r
- case NestedNameSpecifier::Global:\r
- Out << "gs";\r
-\r
- // We want an 'sr' unless this is the entire NNS.\r
- if (recursive)\r
- Out << "sr";\r
-\r
- // We never want an 'E' here.\r
- return;\r
-\r
- case NestedNameSpecifier::Namespace:\r
- if (qualifier->getPrefix())\r
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,\r
- /*recursive*/ true);\r
- else\r
- Out << "sr";\r
- mangleSourceName(qualifier->getAsNamespace()->getIdentifier());\r
- break;\r
- case NestedNameSpecifier::NamespaceAlias:\r
- if (qualifier->getPrefix())\r
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,\r
- /*recursive*/ true);\r
- else\r
- Out << "sr";\r
- mangleSourceName(qualifier->getAsNamespaceAlias()->getIdentifier());\r
- break;\r
-\r
- case NestedNameSpecifier::TypeSpec:\r
- case NestedNameSpecifier::TypeSpecWithTemplate: {\r
- const Type *type = qualifier->getAsType();\r
-\r
- // We only want to use an unresolved-type encoding if this is one of:\r
- // - a decltype\r
- // - a template type parameter\r
- // - a template template parameter with arguments\r
- // In all of these cases, we should have no prefix.\r
- if (qualifier->getPrefix()) {\r
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,\r
- /*recursive*/ true);\r
- } else {\r
- // Otherwise, all the cases want this.\r
- Out << "sr";\r
- }\r
-\r
- // Only certain other types are valid as prefixes; enumerate them.\r
- switch (type->getTypeClass()) {\r
- case Type::Builtin:\r
- case Type::Complex:\r
- case Type::Pointer:\r
- case Type::BlockPointer:\r
- case Type::LValueReference:\r
- case Type::RValueReference:\r
- case Type::MemberPointer:\r
- case Type::ConstantArray:\r
- case Type::IncompleteArray:\r
- case Type::VariableArray:\r
- case Type::DependentSizedArray:\r
- case Type::DependentSizedExtVector:\r
- case Type::Vector:\r
- case Type::ExtVector:\r
- case Type::FunctionProto:\r
- case Type::FunctionNoProto:\r
- case Type::Enum:\r
- case Type::Paren:\r
- case Type::Elaborated:\r
- case Type::Attributed:\r
- case Type::Auto:\r
- case Type::PackExpansion:\r
- case Type::ObjCObject:\r
- case Type::ObjCInterface:\r
- case Type::ObjCObjectPointer:\r
- case Type::Atomic:\r
- llvm_unreachable("type is illegal as a nested name specifier");\r
-\r
- case Type::SubstTemplateTypeParmPack:\r
- // FIXME: not clear how to mangle this!\r
- // template <class T...> class A {\r
- // template <class U...> void foo(decltype(T::foo(U())) x...);\r
- // };\r
- Out << "_SUBSTPACK_";\r
- break;\r
-\r
- // <unresolved-type> ::= <template-param>\r
- // ::= <decltype>\r
- // ::= <template-template-param> <template-args>\r
- // (this last is not official yet)\r
- case Type::TypeOfExpr:\r
- case Type::TypeOf:\r
- case Type::Decltype:\r
- case Type::TemplateTypeParm:\r
- case Type::UnaryTransform:\r
- case Type::SubstTemplateTypeParm:\r
- unresolvedType:\r
- assert(!qualifier->getPrefix());\r
-\r
- // We only get here recursively if we're followed by identifiers.\r
- if (recursive) Out << 'N';\r
-\r
- // This seems to do everything we want. It's not really\r
- // sanctioned for a substituted template parameter, though.\r
- mangleType(QualType(type, 0));\r
-\r
- // We never want to print 'E' directly after an unresolved-type,\r
- // so we return directly.\r
- return;\r
-\r
- case Type::Typedef:\r
- mangleSourceName(cast<TypedefType>(type)->getDecl()->getIdentifier());\r
- break;\r
-\r
- case Type::UnresolvedUsing:\r
- mangleSourceName(cast<UnresolvedUsingType>(type)->getDecl()\r
- ->getIdentifier());\r
- break;\r
-\r
- case Type::Record:\r
- mangleSourceName(cast<RecordType>(type)->getDecl()->getIdentifier());\r
- break;\r
-\r
- case Type::TemplateSpecialization: {\r
- const TemplateSpecializationType *tst\r
- = cast<TemplateSpecializationType>(type);\r
- TemplateName name = tst->getTemplateName();\r
- switch (name.getKind()) {\r
- case TemplateName::Template:\r
- case TemplateName::QualifiedTemplate: {\r
- TemplateDecl *temp = name.getAsTemplateDecl();\r
-\r
- // If the base is a template template parameter, this is an\r
- // unresolved type.\r
- assert(temp && "no template for template specialization type");\r
- if (isa<TemplateTemplateParmDecl>(temp)) goto unresolvedType;\r
-\r
- mangleSourceName(temp->getIdentifier());\r
- break;\r
- }\r
-\r
- case TemplateName::OverloadedTemplate:\r
- case TemplateName::DependentTemplate:\r
- llvm_unreachable("invalid base for a template specialization type");\r
-\r
- case TemplateName::SubstTemplateTemplateParm: {\r
- SubstTemplateTemplateParmStorage *subst\r
- = name.getAsSubstTemplateTemplateParm();\r
- mangleExistingSubstitution(subst->getReplacement());\r
- break;\r
- }\r
-\r
- case TemplateName::SubstTemplateTemplateParmPack: {\r
- // FIXME: not clear how to mangle this!\r
- // template <template <class U> class T...> class A {\r
- // template <class U...> void foo(decltype(T<U>::foo) x...);\r
- // };\r
- Out << "_SUBSTPACK_";\r
- break;\r
- }\r
- }\r
-\r
- mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());\r
- break;\r
- }\r
-\r
- case Type::InjectedClassName:\r
- mangleSourceName(cast<InjectedClassNameType>(type)->getDecl()\r
- ->getIdentifier());\r
- break;\r
-\r
- case Type::DependentName:\r
- mangleSourceName(cast<DependentNameType>(type)->getIdentifier());\r
- break;\r
-\r
- case Type::DependentTemplateSpecialization: {\r
- const DependentTemplateSpecializationType *tst\r
- = cast<DependentTemplateSpecializationType>(type);\r
- mangleSourceName(tst->getIdentifier());\r
- mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());\r
- break;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case NestedNameSpecifier::Identifier:\r
- // Member expressions can have these without prefixes.\r
- if (qualifier->getPrefix()) {\r
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,\r
- /*recursive*/ true);\r
- } else if (firstQualifierLookup) {\r
-\r
- // Try to make a proper qualifier out of the lookup result, and\r
- // then just recurse on that.\r
- NestedNameSpecifier *newQualifier;\r
- if (TypeDecl *typeDecl = dyn_cast<TypeDecl>(firstQualifierLookup)) {\r
- QualType type = getASTContext().getTypeDeclType(typeDecl);\r
-\r
- // Pretend we had a different nested name specifier.\r
- newQualifier = NestedNameSpecifier::Create(getASTContext(),\r
- /*prefix*/ 0,\r
- /*template*/ false,\r
- type.getTypePtr());\r
- } else if (NamespaceDecl *nspace =\r
- dyn_cast<NamespaceDecl>(firstQualifierLookup)) {\r
- newQualifier = NestedNameSpecifier::Create(getASTContext(),\r
- /*prefix*/ 0,\r
- nspace);\r
- } else if (NamespaceAliasDecl *alias =\r
- dyn_cast<NamespaceAliasDecl>(firstQualifierLookup)) {\r
- newQualifier = NestedNameSpecifier::Create(getASTContext(),\r
- /*prefix*/ 0,\r
- alias);\r
- } else {\r
- // No sensible mangling to do here.\r
- newQualifier = 0;\r
- }\r
-\r
- if (newQualifier)\r
- return mangleUnresolvedPrefix(newQualifier, /*lookup*/ 0, recursive);\r
-\r
- } else {\r
- Out << "sr";\r
- }\r
-\r
- mangleSourceName(qualifier->getAsIdentifier());\r
- break;\r
- }\r
-\r
- // If this was the innermost part of the NNS, and we fell out to\r
- // here, append an 'E'.\r
- if (!recursive)\r
- Out << 'E';\r
-}\r
-\r
-/// Mangle an unresolved-name, which is generally used for names which\r
-/// weren't resolved to specific entities.\r
-void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,\r
- NamedDecl *firstQualifierLookup,\r
- DeclarationName name,\r
- unsigned knownArity) {\r
- if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup);\r
- mangleUnqualifiedName(0, name, knownArity);\r
-}\r
-\r
-static const FieldDecl *FindFirstNamedDataMember(const RecordDecl *RD) {\r
- assert(RD->isAnonymousStructOrUnion() &&\r
- "Expected anonymous struct or union!");\r
- \r
- for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();\r
- I != E; ++I) {\r
- if (I->getIdentifier())\r
- return *I;\r
- \r
- if (const RecordType *RT = I->getType()->getAs<RecordType>())\r
- if (const FieldDecl *NamedDataMember = \r
- FindFirstNamedDataMember(RT->getDecl()))\r
- return NamedDataMember;\r
- }\r
-\r
- // We didn't find a named data member.\r
- return 0;\r
-}\r
-\r
-void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,\r
- DeclarationName Name,\r
- unsigned KnownArity) {\r
- // <unqualified-name> ::= <operator-name>\r
- // ::= <ctor-dtor-name>\r
- // ::= <source-name>\r
- switch (Name.getNameKind()) {\r
- case DeclarationName::Identifier: {\r
- if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {\r
- // We must avoid conflicts between internally- and externally-\r
- // linked variable and function declaration names in the same TU:\r
- // void test() { extern void foo(); }\r
- // static void foo();\r
- // This naming convention is the same as that followed by GCC,\r
- // though it shouldn't actually matter.\r
- if (ND && ND->getLinkage() == InternalLinkage &&\r
- getEffectiveDeclContext(ND)->isFileContext())\r
- Out << 'L';\r
-\r
- mangleSourceName(II);\r
- break;\r
- }\r
-\r
- // Otherwise, an anonymous entity. We must have a declaration.\r
- assert(ND && "mangling empty name without declaration");\r
-\r
- if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {\r
- if (NS->isAnonymousNamespace()) {\r
- // This is how gcc mangles these names.\r
- Out << "12_GLOBAL__N_1";\r
- break;\r
- }\r
- }\r
-\r
- if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {\r
- // We must have an anonymous union or struct declaration.\r
- const RecordDecl *RD = \r
- cast<RecordDecl>(VD->getType()->getAs<RecordType>()->getDecl());\r
- \r
- // Itanium C++ ABI 5.1.2:\r
- //\r
- // For the purposes of mangling, the name of an anonymous union is\r
- // considered to be the name of the first named data member found by a\r
- // pre-order, depth-first, declaration-order walk of the data members of\r
- // the anonymous union. If there is no such data member (i.e., if all of\r
- // the data members in the union are unnamed), then there is no way for\r
- // a program to refer to the anonymous union, and there is therefore no\r
- // need to mangle its name.\r
- const FieldDecl *FD = FindFirstNamedDataMember(RD);\r
-\r
- // It's actually possible for various reasons for us to get here\r
- // with an empty anonymous struct / union. Fortunately, it\r
- // doesn't really matter what name we generate.\r
- if (!FD) break;\r
- assert(FD->getIdentifier() && "Data member name isn't an identifier!");\r
- \r
- mangleSourceName(FD->getIdentifier());\r
- break;\r
- }\r
- \r
- // We must have an anonymous struct.\r
- const TagDecl *TD = cast<TagDecl>(ND);\r
- if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) {\r
- assert(TD->getDeclContext() == D->getDeclContext() &&\r
- "Typedef should not be in another decl context!");\r
- assert(D->getDeclName().getAsIdentifierInfo() &&\r
- "Typedef was not named!");\r
- mangleSourceName(D->getDeclName().getAsIdentifierInfo());\r
- break;\r
- }\r
-\r
- // <unnamed-type-name> ::= <closure-type-name>\r
- // \r
- // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _\r
- // <lambda-sig> ::= <parameter-type>+ # Parameter types or 'v' for 'void'.\r
- if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {\r
- if (Record->isLambda() && Record->getLambdaManglingNumber()) {\r
- mangleLambda(Record);\r
- break;\r
- }\r
- }\r
-\r
- int UnnamedMangle = Context.getASTContext().getUnnamedTagManglingNumber(TD);\r
- if (UnnamedMangle != -1) {\r
- Out << "Ut";\r
- if (UnnamedMangle != 0)\r
- Out << llvm::utostr(UnnamedMangle - 1);\r
- Out << '_';\r
- break;\r
- }\r
-\r
- // Get a unique id for the anonymous struct.\r
- uint64_t AnonStructId = Context.getAnonymousStructId(TD);\r
-\r
- // Mangle it as a source name in the form\r
- // [n] $_<id>\r
- // where n is the length of the string.\r
- SmallString<8> Str;\r
- Str += "$_";\r
- Str += llvm::utostr(AnonStructId);\r
-\r
- Out << Str.size();\r
- Out << Str.str();\r
- break;\r
- }\r
-\r
- case DeclarationName::ObjCZeroArgSelector:\r
- case DeclarationName::ObjCOneArgSelector:\r
- case DeclarationName::ObjCMultiArgSelector:\r
- llvm_unreachable("Can't mangle Objective-C selector names here!");\r
-\r
- case DeclarationName::CXXConstructorName:\r
- if (ND == Structor)\r
- // If the named decl is the C++ constructor we're mangling, use the type\r
- // we were given.\r
- mangleCXXCtorType(static_cast<CXXCtorType>(StructorType));\r
- else\r
- // Otherwise, use the complete constructor name. This is relevant if a\r
- // class with a constructor is declared within a constructor.\r
- mangleCXXCtorType(Ctor_Complete);\r
- break;\r
-\r
- case DeclarationName::CXXDestructorName:\r
- if (ND == Structor)\r
- // If the named decl is the C++ destructor we're mangling, use the type we\r
- // were given.\r
- mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));\r
- else\r
- // Otherwise, use the complete destructor name. This is relevant if a\r
- // class with a destructor is declared within a destructor.\r
- mangleCXXDtorType(Dtor_Complete);\r
- break;\r
-\r
- case DeclarationName::CXXConversionFunctionName:\r
- // <operator-name> ::= cv <type> # (cast)\r
- Out << "cv";\r
- mangleType(Name.getCXXNameType());\r
- break;\r
-\r
- case DeclarationName::CXXOperatorName: {\r
- unsigned Arity;\r
- if (ND) {\r
- Arity = cast<FunctionDecl>(ND)->getNumParams();\r
-\r
- // If we have a C++ member function, we need to include the 'this' pointer.\r
- // FIXME: This does not make sense for operators that are static, but their\r
- // names stay the same regardless of the arity (operator new for instance).\r
- if (isa<CXXMethodDecl>(ND))\r
- Arity++;\r
- } else\r
- Arity = KnownArity;\r
-\r
- mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);\r
- break;\r
- }\r
-\r
- case DeclarationName::CXXLiteralOperatorName:\r
- // FIXME: This mangling is not yet official.\r
- Out << "li";\r
- mangleSourceName(Name.getCXXLiteralIdentifier());\r
- break;\r
-\r
- case DeclarationName::CXXUsingDirective:\r
- llvm_unreachable("Can't mangle a using directive name!");\r
- }\r
-}\r
-\r
-void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) {\r
- // <source-name> ::= <positive length number> <identifier>\r
- // <number> ::= [n] <non-negative decimal integer>\r
- // <identifier> ::= <unqualified source code identifier>\r
- Out << II->getLength() << II->getName();\r
-}\r
-\r
-void CXXNameMangler::mangleNestedName(const NamedDecl *ND,\r
- const DeclContext *DC,\r
- bool NoFunction) {\r
- // <nested-name> \r
- // ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E\r
- // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> \r
- // <template-args> E\r
-\r
- Out << 'N';\r
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) {\r
- mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers()));\r
- mangleRefQualifier(Method->getRefQualifier());\r
- }\r
- \r
- // Check if we have a template.\r
- const TemplateArgumentList *TemplateArgs = 0;\r
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {\r
- mangleTemplatePrefix(TD);\r
- mangleTemplateArgs(*TemplateArgs);\r
- }\r
- else {\r
- manglePrefix(DC, NoFunction);\r
- mangleUnqualifiedName(ND);\r
- }\r
-\r
- Out << 'E';\r
-}\r
-void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,\r
- const TemplateArgument *TemplateArgs,\r
- unsigned NumTemplateArgs) {\r
- // <nested-name> ::= N [<CV-qualifiers>] <template-prefix> <template-args> E\r
-\r
- Out << 'N';\r
-\r
- mangleTemplatePrefix(TD);\r
- mangleTemplateArgs(TemplateArgs, NumTemplateArgs);\r
-\r
- Out << 'E';\r
-}\r
-\r
-void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {\r
- // <local-name> := Z <function encoding> E <entity name> [<discriminator>]\r
- // := Z <function encoding> E s [<discriminator>]\r
- // <local-name> := Z <function encoding> E d [ <parameter number> ] \r
- // _ <entity name>\r
- // <discriminator> := _ <non-negative number>\r
- const DeclContext *DC = getEffectiveDeclContext(ND);\r
- if (isa<ObjCMethodDecl>(DC) && isa<FunctionDecl>(ND)) {\r
- // Don't add objc method name mangling to locally declared function\r
- mangleUnqualifiedName(ND);\r
- return;\r
- }\r
-\r
- Out << 'Z';\r
-\r
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) {\r
- mangleObjCMethodName(MD);\r
- } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) {\r
- mangleFunctionEncoding(cast<FunctionDecl>(getEffectiveDeclContext(RD)));\r
- Out << 'E';\r
-\r
- // The parameter number is omitted for the last parameter, 0 for the \r
- // second-to-last parameter, 1 for the third-to-last parameter, etc. The \r
- // <entity name> will of course contain a <closure-type-name>: Its \r
- // numbering will be local to the particular argument in which it appears\r
- // -- other default arguments do not affect its encoding.\r
- bool SkipDiscriminator = false;\r
- if (RD->isLambda()) {\r
- if (const ParmVarDecl *Parm\r
- = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) {\r
- if (const FunctionDecl *Func\r
- = dyn_cast<FunctionDecl>(Parm->getDeclContext())) {\r
- Out << 'd';\r
- unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex();\r
- if (Num > 1)\r
- mangleNumber(Num - 2);\r
- Out << '_';\r
- SkipDiscriminator = true;\r
- }\r
- }\r
- }\r
- \r
- // Mangle the name relative to the closest enclosing function.\r
- if (ND == RD) // equality ok because RD derived from ND above\r
- mangleUnqualifiedName(ND);\r
- else\r
- mangleNestedName(ND, DC, true /*NoFunction*/);\r
-\r
- if (!SkipDiscriminator) {\r
- unsigned disc;\r
- if (Context.getNextDiscriminator(RD, disc)) {\r
- if (disc < 10)\r
- Out << '_' << disc;\r
- else\r
- Out << "__" << disc << '_';\r
- }\r
- }\r
- \r
- return;\r
- }\r
- else\r
- mangleFunctionEncoding(cast<FunctionDecl>(DC));\r
-\r
- Out << 'E';\r
- mangleUnqualifiedName(ND);\r
-}\r
-\r
-void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {\r
- // If the context of a closure type is an initializer for a class member \r
- // (static or nonstatic), it is encoded in a qualified name with a final \r
- // <prefix> of the form:\r
- //\r
- // <data-member-prefix> := <member source-name> M\r
- //\r
- // Technically, the data-member-prefix is part of the <prefix>. However,\r
- // since a closure type will always be mangled with a prefix, it's easier\r
- // to emit that last part of the prefix here.\r
- if (Decl *Context = Lambda->getLambdaContextDecl()) {\r
- if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&\r
- Context->getDeclContext()->isRecord()) {\r
- if (const IdentifierInfo *Name\r
- = cast<NamedDecl>(Context)->getIdentifier()) {\r
- mangleSourceName(Name);\r
- Out << 'M'; \r
- }\r
- }\r
- }\r
-\r
- Out << "Ul";\r
- const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()->\r
- getAs<FunctionProtoType>();\r
- mangleBareFunctionType(Proto, /*MangleReturnType=*/false); \r
- Out << "E";\r
- \r
- // The number is omitted for the first closure type with a given \r
- // <lambda-sig> in a given context; it is n-2 for the nth closure type \r
- // (in lexical order) with that same <lambda-sig> and context.\r
- //\r
- // The AST keeps track of the number for us.\r
- unsigned Number = Lambda->getLambdaManglingNumber();\r
- assert(Number > 0 && "Lambda should be mangled as an unnamed class");\r
- if (Number > 1)\r
- mangleNumber(Number - 2);\r
- Out << '_'; \r
-}\r
-\r
-void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {\r
- switch (qualifier->getKind()) {\r
- case NestedNameSpecifier::Global:\r
- // nothing\r
- return;\r
-\r
- case NestedNameSpecifier::Namespace:\r
- mangleName(qualifier->getAsNamespace());\r
- return;\r
-\r
- case NestedNameSpecifier::NamespaceAlias:\r
- mangleName(qualifier->getAsNamespaceAlias()->getNamespace());\r
- return;\r
-\r
- case NestedNameSpecifier::TypeSpec:\r
- case NestedNameSpecifier::TypeSpecWithTemplate:\r
- manglePrefix(QualType(qualifier->getAsType(), 0));\r
- return;\r
-\r
- case NestedNameSpecifier::Identifier:\r
- // Member expressions can have these without prefixes, but that\r
- // should end up in mangleUnresolvedPrefix instead.\r
- assert(qualifier->getPrefix());\r
- manglePrefix(qualifier->getPrefix());\r
-\r
- mangleSourceName(qualifier->getAsIdentifier());\r
- return;\r
- }\r
-\r
- llvm_unreachable("unexpected nested name specifier");\r
-}\r
-\r
-void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {\r
- // <prefix> ::= <prefix> <unqualified-name>\r
- // ::= <template-prefix> <template-args>\r
- // ::= <template-param>\r
- // ::= # empty\r
- // ::= <substitution>\r
-\r
- DC = IgnoreLinkageSpecDecls(DC);\r
-\r
- if (DC->isTranslationUnit())\r
- return;\r
-\r
- if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) {\r
- manglePrefix(getEffectiveParentContext(DC), NoFunction); \r
- SmallString<64> Name;\r
- llvm::raw_svector_ostream NameStream(Name);\r
- Context.mangleBlock(Block, NameStream);\r
- NameStream.flush();\r
- Out << Name.size() << Name;\r
- return;\r
- }\r
- \r
- const NamedDecl *ND = cast<NamedDecl>(DC); \r
- if (mangleSubstitution(ND))\r
- return;\r
- \r
- // Check if we have a template.\r
- const TemplateArgumentList *TemplateArgs = 0;\r
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {\r
- mangleTemplatePrefix(TD);\r
- mangleTemplateArgs(*TemplateArgs);\r
- }\r
- else if(NoFunction && (isa<FunctionDecl>(ND) || isa<ObjCMethodDecl>(ND)))\r
- return;\r
- else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))\r
- mangleObjCMethodName(Method);\r
- else {\r
- manglePrefix(getEffectiveDeclContext(ND), NoFunction);\r
- mangleUnqualifiedName(ND);\r
- }\r
-\r
- addSubstitution(ND);\r
-}\r
-\r
-void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {\r
- // <template-prefix> ::= <prefix> <template unqualified-name>\r
- // ::= <template-param>\r
- // ::= <substitution>\r
- if (TemplateDecl *TD = Template.getAsTemplateDecl())\r
- return mangleTemplatePrefix(TD);\r
-\r
- if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName())\r
- manglePrefix(Qualified->getQualifier());\r
- \r
- if (OverloadedTemplateStorage *Overloaded\r
- = Template.getAsOverloadedTemplate()) {\r
- mangleUnqualifiedName(0, (*Overloaded->begin())->getDeclName(), \r
- UnknownArity);\r
- return;\r
- }\r
- \r
- DependentTemplateName *Dependent = Template.getAsDependentTemplateName();\r
- assert(Dependent && "Unknown template name kind?");\r
- manglePrefix(Dependent->getQualifier());\r
- mangleUnscopedTemplateName(Template);\r
-}\r
-\r
-void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) {\r
- // <template-prefix> ::= <prefix> <template unqualified-name>\r
- // ::= <template-param>\r
- // ::= <substitution>\r
- // <template-template-param> ::= <template-param>\r
- // <substitution>\r
-\r
- if (mangleSubstitution(ND))\r
- return;\r
-\r
- // <template-template-param> ::= <template-param>\r
- if (const TemplateTemplateParmDecl *TTP\r
- = dyn_cast<TemplateTemplateParmDecl>(ND)) {\r
- mangleTemplateParameter(TTP->getIndex());\r
- return;\r
- }\r
-\r
- manglePrefix(getEffectiveDeclContext(ND));\r
- mangleUnqualifiedName(ND->getTemplatedDecl());\r
- addSubstitution(ND);\r
-}\r
-\r
-/// Mangles a template name under the production <type>. Required for\r
-/// template template arguments.\r
-/// <type> ::= <class-enum-type>\r
-/// ::= <template-param>\r
-/// ::= <substitution>\r
-void CXXNameMangler::mangleType(TemplateName TN) {\r
- if (mangleSubstitution(TN))\r
- return;\r
- \r
- TemplateDecl *TD = 0;\r
-\r
- switch (TN.getKind()) {\r
- case TemplateName::QualifiedTemplate:\r
- TD = TN.getAsQualifiedTemplateName()->getTemplateDecl();\r
- goto HaveDecl;\r
-\r
- case TemplateName::Template:\r
- TD = TN.getAsTemplateDecl();\r
- goto HaveDecl;\r
-\r
- HaveDecl:\r
- if (isa<TemplateTemplateParmDecl>(TD))\r
- mangleTemplateParameter(cast<TemplateTemplateParmDecl>(TD)->getIndex());\r
- else\r
- mangleName(TD);\r
- break;\r
-\r
- case TemplateName::OverloadedTemplate:\r
- llvm_unreachable("can't mangle an overloaded template name as a <type>");\r
-\r
- case TemplateName::DependentTemplate: {\r
- const DependentTemplateName *Dependent = TN.getAsDependentTemplateName();\r
- assert(Dependent->isIdentifier());\r
-\r
- // <class-enum-type> ::= <name>\r
- // <name> ::= <nested-name>\r
- mangleUnresolvedPrefix(Dependent->getQualifier(), 0);\r
- mangleSourceName(Dependent->getIdentifier());\r
- break;\r
- }\r
-\r
- case TemplateName::SubstTemplateTemplateParm: {\r
- // Substituted template parameters are mangled as the substituted\r
- // template. This will check for the substitution twice, which is\r
- // fine, but we have to return early so that we don't try to *add*\r
- // the substitution twice.\r
- SubstTemplateTemplateParmStorage *subst\r
- = TN.getAsSubstTemplateTemplateParm();\r
- mangleType(subst->getReplacement());\r
- return;\r
- }\r
-\r
- case TemplateName::SubstTemplateTemplateParmPack: {\r
- // FIXME: not clear how to mangle this!\r
- // template <template <class> class T...> class A {\r
- // template <template <class> class U...> void foo(B<T,U> x...);\r
- // };\r
- Out << "_SUBSTPACK_";\r
- break;\r
- }\r
- }\r
-\r
- addSubstitution(TN);\r
-}\r
-\r
-void\r
-CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {\r
- switch (OO) {\r
- // <operator-name> ::= nw # new\r
- case OO_New: Out << "nw"; break;\r
- // ::= na # new[]\r
- case OO_Array_New: Out << "na"; break;\r
- // ::= dl # delete\r
- case OO_Delete: Out << "dl"; break;\r
- // ::= da # delete[]\r
- case OO_Array_Delete: Out << "da"; break;\r
- // ::= ps # + (unary)\r
- // ::= pl # + (binary or unknown)\r
- case OO_Plus:\r
- Out << (Arity == 1? "ps" : "pl"); break;\r
- // ::= ng # - (unary)\r
- // ::= mi # - (binary or unknown)\r
- case OO_Minus:\r
- Out << (Arity == 1? "ng" : "mi"); break;\r
- // ::= ad # & (unary)\r
- // ::= an # & (binary or unknown)\r
- case OO_Amp:\r
- Out << (Arity == 1? "ad" : "an"); break;\r
- // ::= de # * (unary)\r
- // ::= ml # * (binary or unknown)\r
- case OO_Star:\r
- // Use binary when unknown.\r
- Out << (Arity == 1? "de" : "ml"); break;\r
- // ::= co # ~\r
- case OO_Tilde: Out << "co"; break;\r
- // ::= dv # /\r
- case OO_Slash: Out << "dv"; break;\r
- // ::= rm # %\r
- case OO_Percent: Out << "rm"; break;\r
- // ::= or # |\r
- case OO_Pipe: Out << "or"; break;\r
- // ::= eo # ^\r
- case OO_Caret: Out << "eo"; break;\r
- // ::= aS # =\r
- case OO_Equal: Out << "aS"; break;\r
- // ::= pL # +=\r
- case OO_PlusEqual: Out << "pL"; break;\r
- // ::= mI # -=\r
- case OO_MinusEqual: Out << "mI"; break;\r
- // ::= mL # *=\r
- case OO_StarEqual: Out << "mL"; break;\r
- // ::= dV # /=\r
- case OO_SlashEqual: Out << "dV"; break;\r
- // ::= rM # %=\r
- case OO_PercentEqual: Out << "rM"; break;\r
- // ::= aN # &=\r
- case OO_AmpEqual: Out << "aN"; break;\r
- // ::= oR # |=\r
- case OO_PipeEqual: Out << "oR"; break;\r
- // ::= eO # ^=\r
- case OO_CaretEqual: Out << "eO"; break;\r
- // ::= ls # <<\r
- case OO_LessLess: Out << "ls"; break;\r
- // ::= rs # >>\r
- case OO_GreaterGreater: Out << "rs"; break;\r
- // ::= lS # <<=\r
- case OO_LessLessEqual: Out << "lS"; break;\r
- // ::= rS # >>=\r
- case OO_GreaterGreaterEqual: Out << "rS"; break;\r
- // ::= eq # ==\r
- case OO_EqualEqual: Out << "eq"; break;\r
- // ::= ne # !=\r
- case OO_ExclaimEqual: Out << "ne"; break;\r
- // ::= lt # <\r
- case OO_Less: Out << "lt"; break;\r
- // ::= gt # >\r
- case OO_Greater: Out << "gt"; break;\r
- // ::= le # <=\r
- case OO_LessEqual: Out << "le"; break;\r
- // ::= ge # >=\r
- case OO_GreaterEqual: Out << "ge"; break;\r
- // ::= nt # !\r
- case OO_Exclaim: Out << "nt"; break;\r
- // ::= aa # &&\r
- case OO_AmpAmp: Out << "aa"; break;\r
- // ::= oo # ||\r
- case OO_PipePipe: Out << "oo"; break;\r
- // ::= pp # ++\r
- case OO_PlusPlus: Out << "pp"; break;\r
- // ::= mm # --\r
- case OO_MinusMinus: Out << "mm"; break;\r
- // ::= cm # ,\r
- case OO_Comma: Out << "cm"; break;\r
- // ::= pm # ->*\r
- case OO_ArrowStar: Out << "pm"; break;\r
- // ::= pt # ->\r
- case OO_Arrow: Out << "pt"; break;\r
- // ::= cl # ()\r
- case OO_Call: Out << "cl"; break;\r
- // ::= ix # []\r
- case OO_Subscript: Out << "ix"; break;\r
-\r
- // ::= qu # ?\r
- // The conditional operator can't be overloaded, but we still handle it when\r
- // mangling expressions.\r
- case OO_Conditional: Out << "qu"; break;\r
-\r
- case OO_None:\r
- case NUM_OVERLOADED_OPERATORS:\r
- llvm_unreachable("Not an overloaded operator");\r
- }\r
-}\r
-\r
-void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {\r
- // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const\r
- if (Quals.hasRestrict())\r
- Out << 'r';\r
- if (Quals.hasVolatile())\r
- Out << 'V';\r
- if (Quals.hasConst())\r
- Out << 'K';\r
-\r
- if (Quals.hasAddressSpace()) {\r
- // Extension:\r
- //\r
- // <type> ::= U <address-space-number>\r
- // \r
- // where <address-space-number> is a source name consisting of 'AS' \r
- // followed by the address space <number>.\r
- SmallString<64> ASString;\r
- ASString = "AS" + llvm::utostr_32(Quals.getAddressSpace());\r
- Out << 'U' << ASString.size() << ASString;\r
- }\r
- \r
- StringRef LifetimeName;\r
- switch (Quals.getObjCLifetime()) {\r
- // Objective-C ARC Extension:\r
- //\r
- // <type> ::= U "__strong"\r
- // <type> ::= U "__weak"\r
- // <type> ::= U "__autoreleasing"\r
- case Qualifiers::OCL_None:\r
- break;\r
- \r
- case Qualifiers::OCL_Weak:\r
- LifetimeName = "__weak";\r
- break;\r
- \r
- case Qualifiers::OCL_Strong:\r
- LifetimeName = "__strong";\r
- break;\r
- \r
- case Qualifiers::OCL_Autoreleasing:\r
- LifetimeName = "__autoreleasing";\r
- break;\r
- \r
- case Qualifiers::OCL_ExplicitNone:\r
- // The __unsafe_unretained qualifier is *not* mangled, so that\r
- // __unsafe_unretained types in ARC produce the same manglings as the\r
- // equivalent (but, naturally, unqualified) types in non-ARC, providing\r
- // better ABI compatibility.\r
- //\r
- // It's safe to do this because unqualified 'id' won't show up\r
- // in any type signatures that need to be mangled.\r
- break;\r
- }\r
- if (!LifetimeName.empty())\r
- Out << 'U' << LifetimeName.size() << LifetimeName;\r
-}\r
-\r
-void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {\r
- // <ref-qualifier> ::= R # lvalue reference\r
- // ::= O # rvalue-reference\r
- // Proposal to Itanium C++ ABI list on 1/26/11\r
- switch (RefQualifier) {\r
- case RQ_None:\r
- break;\r
- \r
- case RQ_LValue:\r
- Out << 'R';\r
- break;\r
- \r
- case RQ_RValue:\r
- Out << 'O';\r
- break;\r
- }\r
-}\r
-\r
-void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {\r
- Context.mangleObjCMethodName(MD, Out);\r
-}\r
-\r
-void CXXNameMangler::mangleType(QualType T) {\r
- // If our type is instantiation-dependent but not dependent, we mangle\r
- // it as it was written in the source, removing any top-level sugar. \r
- // Otherwise, use the canonical type.\r
- //\r
- // FIXME: This is an approximation of the instantiation-dependent name \r
- // mangling rules, since we should really be using the type as written and\r
- // augmented via semantic analysis (i.e., with implicit conversions and\r
- // default template arguments) for any instantiation-dependent type. \r
- // Unfortunately, that requires several changes to our AST:\r
- // - Instantiation-dependent TemplateSpecializationTypes will need to be \r
- // uniqued, so that we can handle substitutions properly\r
- // - Default template arguments will need to be represented in the\r
- // TemplateSpecializationType, since they need to be mangled even though\r
- // they aren't written.\r
- // - Conversions on non-type template arguments need to be expressed, since\r
- // they can affect the mangling of sizeof/alignof.\r
- if (!T->isInstantiationDependentType() || T->isDependentType())\r
- T = T.getCanonicalType();\r
- else {\r
- // Desugar any types that are purely sugar.\r
- do {\r
- // Don't desugar through template specialization types that aren't\r
- // type aliases. We need to mangle the template arguments as written.\r
- if (const TemplateSpecializationType *TST \r
- = dyn_cast<TemplateSpecializationType>(T))\r
- if (!TST->isTypeAlias())\r
- break;\r
-\r
- QualType Desugared \r
- = T.getSingleStepDesugaredType(Context.getASTContext());\r
- if (Desugared == T)\r
- break;\r
- \r
- T = Desugared;\r
- } while (true);\r
- }\r
- SplitQualType split = T.split();\r
- Qualifiers quals = split.Quals;\r
- const Type *ty = split.Ty;\r
-\r
- bool isSubstitutable = quals || !isa<BuiltinType>(T);\r
- if (isSubstitutable && mangleSubstitution(T))\r
- return;\r
-\r
- // If we're mangling a qualified array type, push the qualifiers to\r
- // the element type.\r
- if (quals && isa<ArrayType>(T)) {\r
- ty = Context.getASTContext().getAsArrayType(T);\r
- quals = Qualifiers();\r
-\r
- // Note that we don't update T: we want to add the\r
- // substitution at the original type.\r
- }\r
-\r
- if (quals) {\r
- mangleQualifiers(quals);\r
- // Recurse: even if the qualified type isn't yet substitutable,\r
- // the unqualified type might be.\r
- mangleType(QualType(ty, 0));\r
- } else {\r
- switch (ty->getTypeClass()) {\r
-#define ABSTRACT_TYPE(CLASS, PARENT)\r
-#define NON_CANONICAL_TYPE(CLASS, PARENT) \\r
- case Type::CLASS: \\r
- llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \\r
- return;\r
-#define TYPE(CLASS, PARENT) \\r
- case Type::CLASS: \\r
- mangleType(static_cast<const CLASS##Type*>(ty)); \\r
- break;\r
-#include "clang/AST/TypeNodes.def"\r
- }\r
- }\r
-\r
- // Add the substitution.\r
- if (isSubstitutable)\r
- addSubstitution(T);\r
-}\r
-\r
-void CXXNameMangler::mangleNameOrStandardSubstitution(const NamedDecl *ND) {\r
- if (!mangleStandardSubstitution(ND))\r
- mangleName(ND);\r
-}\r
-\r
-void CXXNameMangler::mangleType(const BuiltinType *T) {\r
- // <type> ::= <builtin-type>\r
- // <builtin-type> ::= v # void\r
- // ::= w # wchar_t\r
- // ::= b # bool\r
- // ::= c # char\r
- // ::= a # signed char\r
- // ::= h # unsigned char\r
- // ::= s # short\r
- // ::= t # unsigned short\r
- // ::= i # int\r
- // ::= j # unsigned int\r
- // ::= l # long\r
- // ::= m # unsigned long\r
- // ::= x # long long, __int64\r
- // ::= y # unsigned long long, __int64\r
- // ::= n # __int128\r
- // UNSUPPORTED: ::= o # unsigned __int128\r
- // ::= f # float\r
- // ::= d # double\r
- // ::= e # long double, __float80\r
- // UNSUPPORTED: ::= g # __float128\r
- // UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits)\r
- // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits)\r
- // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits)\r
- // ::= Dh # IEEE 754r half-precision floating point (16 bits)\r
- // ::= Di # char32_t\r
- // ::= Ds # char16_t\r
- // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))\r
- // ::= u <source-name> # vendor extended type\r
- switch (T->getKind()) {\r
- case BuiltinType::Void: Out << 'v'; break;\r
- case BuiltinType::Bool: Out << 'b'; break;\r
- case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'c'; break;\r
- case BuiltinType::UChar: Out << 'h'; break;\r
- case BuiltinType::UShort: Out << 't'; break;\r
- case BuiltinType::UInt: Out << 'j'; break;\r
- case BuiltinType::ULong: Out << 'm'; break;\r
- case BuiltinType::ULongLong: Out << 'y'; break;\r
- case BuiltinType::UInt128: Out << 'o'; break;\r
- case BuiltinType::SChar: Out << 'a'; break;\r
- case BuiltinType::WChar_S:\r
- case BuiltinType::WChar_U: Out << 'w'; break;\r
- case BuiltinType::Char16: Out << "Ds"; break;\r
- case BuiltinType::Char32: Out << "Di"; break;\r
- case BuiltinType::Short: Out << 's'; break;\r
- case BuiltinType::Int: Out << 'i'; break;\r
- case BuiltinType::Long: Out << 'l'; break;\r
- case BuiltinType::LongLong: Out << 'x'; break;\r
- case BuiltinType::Int128: Out << 'n'; break;\r
- case BuiltinType::Half: Out << "Dh"; break;\r
- case BuiltinType::Float: Out << 'f'; break;\r
- case BuiltinType::Double: Out << 'd'; break;\r
- case BuiltinType::LongDouble: Out << 'e'; break;\r
- case BuiltinType::NullPtr: Out << "Dn"; break;\r
-\r
-#define BUILTIN_TYPE(Id, SingletonId)\r
-#define PLACEHOLDER_TYPE(Id, SingletonId) \\r
- case BuiltinType::Id:\r
-#include "clang/AST/BuiltinTypes.def"\r
- case BuiltinType::Dependent:\r
- llvm_unreachable("mangling a placeholder type");\r
- case BuiltinType::ObjCId: Out << "11objc_object"; break;\r
- case BuiltinType::ObjCClass: Out << "10objc_class"; break;\r
- case BuiltinType::ObjCSel: Out << "13objc_selector"; break;\r
- case BuiltinType::OCLImage1d: Out << "11ocl_image1d"; break;\r
- case BuiltinType::OCLImage1dArray: Out << "16ocl_image1darray"; break;\r
- case BuiltinType::OCLImage1dBuffer: Out << "17ocl_image1dbuffer"; break;\r
- case BuiltinType::OCLImage2d: Out << "11ocl_image2d"; break;\r
- case BuiltinType::OCLImage2dArray: Out << "16ocl_image2darray"; break;\r
- case BuiltinType::OCLImage3d: Out << "11ocl_image3d"; break;\r
- }\r
-}\r
-\r
-// <type> ::= <function-type>\r
-// <function-type> ::= [<CV-qualifiers>] F [Y]\r
-// <bare-function-type> [<ref-qualifier>] E\r
-// (Proposal to cxx-abi-dev, 2012-05-11)\r
-void CXXNameMangler::mangleType(const FunctionProtoType *T) {\r
- // Mangle CV-qualifiers, if present. These are 'this' qualifiers,\r
- // e.g. "const" in "int (A::*)() const".\r
- mangleQualifiers(Qualifiers::fromCVRMask(T->getTypeQuals()));\r
-\r
- Out << 'F';\r
-\r
- // FIXME: We don't have enough information in the AST to produce the 'Y'\r
- // encoding for extern "C" function types.\r
- mangleBareFunctionType(T, /*MangleReturnType=*/true);\r
-\r
- // Mangle the ref-qualifier, if present.\r
- mangleRefQualifier(T->getRefQualifier());\r
-\r
- Out << 'E';\r
-}\r
-void CXXNameMangler::mangleType(const FunctionNoProtoType *T) {\r
- llvm_unreachable("Can't mangle K&R function prototypes");\r
-}\r
-void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,\r
- bool MangleReturnType) {\r
- // We should never be mangling something without a prototype.\r
- const FunctionProtoType *Proto = cast<FunctionProtoType>(T);\r
-\r
- // Record that we're in a function type. See mangleFunctionParam\r
- // for details on what we're trying to achieve here.\r
- FunctionTypeDepthState saved = FunctionTypeDepth.push();\r
-\r
- // <bare-function-type> ::= <signature type>+\r
- if (MangleReturnType) {\r
- FunctionTypeDepth.enterResultType();\r
- mangleType(Proto->getResultType());\r
- FunctionTypeDepth.leaveResultType();\r
- }\r
-\r
- if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {\r
- // <builtin-type> ::= v # void\r
- Out << 'v';\r
-\r
- FunctionTypeDepth.pop(saved);\r
- return;\r
- }\r
-\r
- for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),\r
- ArgEnd = Proto->arg_type_end();\r
- Arg != ArgEnd; ++Arg)\r
- mangleType(Context.getASTContext().getSignatureParameterType(*Arg));\r
-\r
- FunctionTypeDepth.pop(saved);\r
-\r
- // <builtin-type> ::= z # ellipsis\r
- if (Proto->isVariadic())\r
- Out << 'z';\r
-}\r
-\r
-// <type> ::= <class-enum-type>\r
-// <class-enum-type> ::= <name>\r
-void CXXNameMangler::mangleType(const UnresolvedUsingType *T) {\r
- mangleName(T->getDecl());\r
-}\r
-\r
-// <type> ::= <class-enum-type>\r
-// <class-enum-type> ::= <name>\r
-void CXXNameMangler::mangleType(const EnumType *T) {\r
- mangleType(static_cast<const TagType*>(T));\r
-}\r
-void CXXNameMangler::mangleType(const RecordType *T) {\r
- mangleType(static_cast<const TagType*>(T));\r
-}\r
-void CXXNameMangler::mangleType(const TagType *T) {\r
- mangleName(T->getDecl());\r
-}\r
-\r
-// <type> ::= <array-type>\r
-// <array-type> ::= A <positive dimension number> _ <element type>\r
-// ::= A [<dimension expression>] _ <element type>\r
-void CXXNameMangler::mangleType(const ConstantArrayType *T) {\r
- Out << 'A' << T->getSize() << '_';\r
- mangleType(T->getElementType());\r
-}\r
-void CXXNameMangler::mangleType(const VariableArrayType *T) {\r
- Out << 'A';\r
- // decayed vla types (size 0) will just be skipped.\r
- if (T->getSizeExpr())\r
- mangleExpression(T->getSizeExpr());\r
- Out << '_';\r
- mangleType(T->getElementType());\r
-}\r
-void CXXNameMangler::mangleType(const DependentSizedArrayType *T) {\r
- Out << 'A';\r
- mangleExpression(T->getSizeExpr());\r
- Out << '_';\r
- mangleType(T->getElementType());\r
-}\r
-void CXXNameMangler::mangleType(const IncompleteArrayType *T) {\r
- Out << "A_";\r
- mangleType(T->getElementType());\r
-}\r
-\r
-// <type> ::= <pointer-to-member-type>\r
-// <pointer-to-member-type> ::= M <class type> <member type>\r
-void CXXNameMangler::mangleType(const MemberPointerType *T) {\r
- Out << 'M';\r
- mangleType(QualType(T->getClass(), 0));\r
- QualType PointeeType = T->getPointeeType();\r
- if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {\r
- mangleType(FPT);\r
- \r
- // Itanium C++ ABI 5.1.8:\r
- //\r
- // The type of a non-static member function is considered to be different,\r
- // for the purposes of substitution, from the type of a namespace-scope or\r
- // static member function whose type appears similar. The types of two\r
- // non-static member functions are considered to be different, for the\r
- // purposes of substitution, if the functions are members of different\r
- // classes. In other words, for the purposes of substitution, the class of \r
- // which the function is a member is considered part of the type of \r
- // function.\r
-\r
- // Given that we already substitute member function pointers as a\r
- // whole, the net effect of this rule is just to unconditionally\r
- // suppress substitution on the function type in a member pointer.\r
- // We increment the SeqID here to emulate adding an entry to the\r
- // substitution table.\r
- ++SeqID;\r
- } else\r
- mangleType(PointeeType);\r
-}\r
-\r
-// <type> ::= <template-param>\r
-void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {\r
- mangleTemplateParameter(T->getIndex());\r
-}\r
-\r
-// <type> ::= <template-param>\r
-void CXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T) {\r
- // FIXME: not clear how to mangle this!\r
- // template <class T...> class A {\r
- // template <class U...> void foo(T(*)(U) x...);\r
- // };\r
- Out << "_SUBSTPACK_";\r
-}\r
-\r
-// <type> ::= P <type> # pointer-to\r
-void CXXNameMangler::mangleType(const PointerType *T) {\r
- Out << 'P';\r
- mangleType(T->getPointeeType());\r
-}\r
-void CXXNameMangler::mangleType(const ObjCObjectPointerType *T) {\r
- Out << 'P';\r
- mangleType(T->getPointeeType());\r
-}\r
-\r
-// <type> ::= R <type> # reference-to\r
-void CXXNameMangler::mangleType(const LValueReferenceType *T) {\r
- Out << 'R';\r
- mangleType(T->getPointeeType());\r
-}\r
-\r
-// <type> ::= O <type> # rvalue reference-to (C++0x)\r
-void CXXNameMangler::mangleType(const RValueReferenceType *T) {\r
- Out << 'O';\r
- mangleType(T->getPointeeType());\r
-}\r
-\r
-// <type> ::= C <type> # complex pair (C 2000)\r
-void CXXNameMangler::mangleType(const ComplexType *T) {\r
- Out << 'C';\r
- mangleType(T->getElementType());\r
-}\r
-\r
-// ARM's ABI for Neon vector types specifies that they should be mangled as\r
-// if they are structs (to match ARM's initial implementation). The\r
-// vector type must be one of the special types predefined by ARM.\r
-void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {\r
- QualType EltType = T->getElementType();\r
- assert(EltType->isBuiltinType() && "Neon vector element not a BuiltinType");\r
- const char *EltName = 0;\r
- if (T->getVectorKind() == VectorType::NeonPolyVector) {\r
- switch (cast<BuiltinType>(EltType)->getKind()) {\r
- case BuiltinType::SChar: EltName = "poly8_t"; break;\r
- case BuiltinType::Short: EltName = "poly16_t"; break;\r
- default: llvm_unreachable("unexpected Neon polynomial vector element type");\r
- }\r
- } else {\r
- switch (cast<BuiltinType>(EltType)->getKind()) {\r
- case BuiltinType::SChar: EltName = "int8_t"; break;\r
- case BuiltinType::UChar: EltName = "uint8_t"; break;\r
- case BuiltinType::Short: EltName = "int16_t"; break;\r
- case BuiltinType::UShort: EltName = "uint16_t"; break;\r
- case BuiltinType::Int: EltName = "int32_t"; break;\r
- case BuiltinType::UInt: EltName = "uint32_t"; break;\r
- case BuiltinType::LongLong: EltName = "int64_t"; break;\r
- case BuiltinType::ULongLong: EltName = "uint64_t"; break;\r
- case BuiltinType::Float: EltName = "float32_t"; break;\r
- default: llvm_unreachable("unexpected Neon vector element type");\r
- }\r
- }\r
- const char *BaseName = 0;\r
- unsigned BitSize = (T->getNumElements() *\r
- getASTContext().getTypeSize(EltType));\r
- if (BitSize == 64)\r
- BaseName = "__simd64_";\r
- else {\r
- assert(BitSize == 128 && "Neon vector type not 64 or 128 bits");\r
- BaseName = "__simd128_";\r
- }\r
- Out << strlen(BaseName) + strlen(EltName);\r
- Out << BaseName << EltName;\r
-}\r
-\r
-// GNU extension: vector types\r
-// <type> ::= <vector-type>\r
-// <vector-type> ::= Dv <positive dimension number> _\r
-// <extended element type>\r
-// ::= Dv [<dimension expression>] _ <element type>\r
-// <extended element type> ::= <element type>\r
-// ::= p # AltiVec vector pixel\r
-// ::= b # Altivec vector bool\r
-void CXXNameMangler::mangleType(const VectorType *T) {\r
- if ((T->getVectorKind() == VectorType::NeonVector ||\r
- T->getVectorKind() == VectorType::NeonPolyVector)) {\r
- mangleNeonVectorType(T);\r
- return;\r
- }\r
- Out << "Dv" << T->getNumElements() << '_';\r
- if (T->getVectorKind() == VectorType::AltiVecPixel)\r
- Out << 'p';\r
- else if (T->getVectorKind() == VectorType::AltiVecBool)\r
- Out << 'b';\r
- else\r
- mangleType(T->getElementType());\r
-}\r
-void CXXNameMangler::mangleType(const ExtVectorType *T) {\r
- mangleType(static_cast<const VectorType*>(T));\r
-}\r
-void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {\r
- Out << "Dv";\r
- mangleExpression(T->getSizeExpr());\r
- Out << '_';\r
- mangleType(T->getElementType());\r
-}\r
-\r
-void CXXNameMangler::mangleType(const PackExpansionType *T) {\r
- // <type> ::= Dp <type> # pack expansion (C++0x)\r
- Out << "Dp";\r
- mangleType(T->getPattern());\r
-}\r
-\r
-void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {\r
- mangleSourceName(T->getDecl()->getIdentifier());\r
-}\r
-\r
-void CXXNameMangler::mangleType(const ObjCObjectType *T) {\r
- // We don't allow overloading by different protocol qualification,\r
- // so mangling them isn't necessary.\r
- mangleType(T->getBaseType());\r
-}\r
-\r
-void CXXNameMangler::mangleType(const BlockPointerType *T) {\r
- Out << "U13block_pointer";\r
- mangleType(T->getPointeeType());\r
-}\r
-\r
-void CXXNameMangler::mangleType(const InjectedClassNameType *T) {\r
- // Mangle injected class name types as if the user had written the\r
- // specialization out fully. It may not actually be possible to see\r
- // this mangling, though.\r
- mangleType(T->getInjectedSpecializationType());\r
-}\r
-\r
-void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {\r
- if (TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl()) {\r
- mangleName(TD, T->getArgs(), T->getNumArgs());\r
- } else {\r
- if (mangleSubstitution(QualType(T, 0)))\r
- return;\r
- \r
- mangleTemplatePrefix(T->getTemplateName());\r
- \r
- // FIXME: GCC does not appear to mangle the template arguments when\r
- // the template in question is a dependent template name. Should we\r
- // emulate that badness?\r
- mangleTemplateArgs(T->getArgs(), T->getNumArgs());\r
- addSubstitution(QualType(T, 0));\r
- }\r
-}\r
-\r
-void CXXNameMangler::mangleType(const DependentNameType *T) {\r
- // Typename types are always nested\r
- Out << 'N';\r
- manglePrefix(T->getQualifier());\r
- mangleSourceName(T->getIdentifier()); \r
- Out << 'E';\r
-}\r
-\r
-void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) {\r
- // Dependently-scoped template types are nested if they have a prefix.\r
- Out << 'N';\r
-\r
- // TODO: avoid making this TemplateName.\r
- TemplateName Prefix =\r
- getASTContext().getDependentTemplateName(T->getQualifier(),\r
- T->getIdentifier());\r
- mangleTemplatePrefix(Prefix);\r
-\r
- // FIXME: GCC does not appear to mangle the template arguments when\r
- // the template in question is a dependent template name. Should we\r
- // emulate that badness?\r
- mangleTemplateArgs(T->getArgs(), T->getNumArgs()); \r
- Out << 'E';\r
-}\r
-\r
-void CXXNameMangler::mangleType(const TypeOfType *T) {\r
- // FIXME: this is pretty unsatisfactory, but there isn't an obvious\r
- // "extension with parameters" mangling.\r
- Out << "u6typeof";\r
-}\r
-\r
-void CXXNameMangler::mangleType(const TypeOfExprType *T) {\r
- // FIXME: this is pretty unsatisfactory, but there isn't an obvious\r
- // "extension with parameters" mangling.\r
- Out << "u6typeof";\r
-}\r
-\r
-void CXXNameMangler::mangleType(const DecltypeType *T) {\r
- Expr *E = T->getUnderlyingExpr();\r
-\r
- // type ::= Dt <expression> E # decltype of an id-expression\r
- // # or class member access\r
- // ::= DT <expression> E # decltype of an expression\r
-\r
- // This purports to be an exhaustive list of id-expressions and\r
- // class member accesses. Note that we do not ignore parentheses;\r
- // parentheses change the semantics of decltype for these\r
- // expressions (and cause the mangler to use the other form).\r
- if (isa<DeclRefExpr>(E) ||\r
- isa<MemberExpr>(E) ||\r
- isa<UnresolvedLookupExpr>(E) ||\r
- isa<DependentScopeDeclRefExpr>(E) ||\r
- isa<CXXDependentScopeMemberExpr>(E) ||\r
- isa<UnresolvedMemberExpr>(E))\r
- Out << "Dt";\r
- else\r
- Out << "DT";\r
- mangleExpression(E);\r
- Out << 'E';\r
-}\r
-\r
-void CXXNameMangler::mangleType(const UnaryTransformType *T) {\r
- // If this is dependent, we need to record that. If not, we simply\r
- // mangle it as the underlying type since they are equivalent.\r
- if (T->isDependentType()) {\r
- Out << 'U';\r
- \r
- switch (T->getUTTKind()) {\r
- case UnaryTransformType::EnumUnderlyingType:\r
- Out << "3eut";\r
- break;\r
- }\r
- }\r
-\r
- mangleType(T->getUnderlyingType());\r
-}\r
-\r
-void CXXNameMangler::mangleType(const AutoType *T) {\r
- QualType D = T->getDeducedType();\r
- // <builtin-type> ::= Da # dependent auto\r
- if (D.isNull())\r
- Out << "Da";\r
- else\r
- mangleType(D);\r
-}\r
-\r
-void CXXNameMangler::mangleType(const AtomicType *T) {\r
- // <type> ::= U <source-name> <type> # vendor extended type qualifier\r
- // (Until there's a standardized mangling...)\r
- Out << "U7_Atomic";\r
- mangleType(T->getValueType());\r
-}\r
-\r
-void CXXNameMangler::mangleIntegerLiteral(QualType T,\r
- const llvm::APSInt &Value) {\r
- // <expr-primary> ::= L <type> <value number> E # integer literal\r
- Out << 'L';\r
-\r
- mangleType(T);\r
- if (T->isBooleanType()) {\r
- // Boolean values are encoded as 0/1.\r
- Out << (Value.getBoolValue() ? '1' : '0');\r
- } else {\r
- mangleNumber(Value);\r
- }\r
- Out << 'E';\r
-\r
-}\r
-\r
-/// Mangles a member expression.\r
-void CXXNameMangler::mangleMemberExpr(const Expr *base,\r
- bool isArrow,\r
- NestedNameSpecifier *qualifier,\r
- NamedDecl *firstQualifierLookup,\r
- DeclarationName member,\r
- unsigned arity) {\r
- // <expression> ::= dt <expression> <unresolved-name>\r
- // ::= pt <expression> <unresolved-name>\r
- if (base) {\r
- if (base->isImplicitCXXThis()) {\r
- // Note: GCC mangles member expressions to the implicit 'this' as\r
- // *this., whereas we represent them as this->. The Itanium C++ ABI\r
- // does not specify anything here, so we follow GCC.\r
- Out << "dtdefpT";\r
- } else {\r
- Out << (isArrow ? "pt" : "dt");\r
- mangleExpression(base);\r
- }\r
- }\r
- mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity);\r
-}\r
-\r
-/// Look at the callee of the given call expression and determine if\r
-/// it's a parenthesized id-expression which would have triggered ADL\r
-/// otherwise.\r
-static bool isParenthesizedADLCallee(const CallExpr *call) {\r
- const Expr *callee = call->getCallee();\r
- const Expr *fn = callee->IgnoreParens();\r
-\r
- // Must be parenthesized. IgnoreParens() skips __extension__ nodes,\r
- // too, but for those to appear in the callee, it would have to be\r
- // parenthesized.\r
- if (callee == fn) return false;\r
-\r
- // Must be an unresolved lookup.\r
- const UnresolvedLookupExpr *lookup = dyn_cast<UnresolvedLookupExpr>(fn);\r
- if (!lookup) return false;\r
-\r
- assert(!lookup->requiresADL());\r
-\r
- // Must be an unqualified lookup.\r
- if (lookup->getQualifier()) return false;\r
-\r
- // Must not have found a class member. Note that if one is a class\r
- // member, they're all class members.\r
- if (lookup->getNumDecls() > 0 &&\r
- (*lookup->decls_begin())->isCXXClassMember())\r
- return false;\r
-\r
- // Otherwise, ADL would have been triggered.\r
- return true;\r
-}\r
-\r
-void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {\r
- // <expression> ::= <unary operator-name> <expression>\r
- // ::= <binary operator-name> <expression> <expression>\r
- // ::= <trinary operator-name> <expression> <expression> <expression>\r
- // ::= cv <type> expression # conversion with one argument\r
- // ::= cv <type> _ <expression>* E # conversion with a different number of arguments\r
- // ::= st <type> # sizeof (a type)\r
- // ::= at <type> # alignof (a type)\r
- // ::= <template-param>\r
- // ::= <function-param>\r
- // ::= sr <type> <unqualified-name> # dependent name\r
- // ::= sr <type> <unqualified-name> <template-args> # dependent template-id\r
- // ::= ds <expression> <expression> # expr.*expr\r
- // ::= sZ <template-param> # size of a parameter pack\r
- // ::= sZ <function-param> # size of a function parameter pack\r
- // ::= <expr-primary>\r
- // <expr-primary> ::= L <type> <value number> E # integer literal\r
- // ::= L <type <value float> E # floating literal\r
- // ::= L <mangled-name> E # external name\r
- // ::= fpT # 'this' expression\r
- QualType ImplicitlyConvertedToType;\r
- \r
-recurse:\r
- switch (E->getStmtClass()) {\r
- case Expr::NoStmtClass:\r
-#define ABSTRACT_STMT(Type)\r
-#define EXPR(Type, Base)\r
-#define STMT(Type, Base) \\r
- case Expr::Type##Class:\r
-#include "clang/AST/StmtNodes.inc"\r
- // fallthrough\r
-\r
- // These all can only appear in local or variable-initialization\r
- // contexts and so should never appear in a mangling.\r
- case Expr::AddrLabelExprClass:\r
- case Expr::DesignatedInitExprClass:\r
- case Expr::ImplicitValueInitExprClass:\r
- case Expr::ParenListExprClass:\r
- case Expr::LambdaExprClass:\r
- llvm_unreachable("unexpected statement kind");\r
-\r
- // FIXME: invent manglings for all these.\r
- case Expr::BlockExprClass:\r
- case Expr::CXXPseudoDestructorExprClass:\r
- case Expr::ChooseExprClass:\r
- case Expr::CompoundLiteralExprClass:\r
- case Expr::ExtVectorElementExprClass:\r
- case Expr::GenericSelectionExprClass:\r
- case Expr::ObjCEncodeExprClass:\r
- case Expr::ObjCIsaExprClass:\r
- case Expr::ObjCIvarRefExprClass:\r
- case Expr::ObjCMessageExprClass:\r
- case Expr::ObjCPropertyRefExprClass:\r
- case Expr::ObjCProtocolExprClass:\r
- case Expr::ObjCSelectorExprClass:\r
- case Expr::ObjCStringLiteralClass:\r
- case Expr::ObjCBoxedExprClass:\r
- case Expr::ObjCArrayLiteralClass:\r
- case Expr::ObjCDictionaryLiteralClass:\r
- case Expr::ObjCSubscriptRefExprClass:\r
- case Expr::ObjCIndirectCopyRestoreExprClass:\r
- case Expr::OffsetOfExprClass:\r
- case Expr::PredefinedExprClass:\r
- case Expr::ShuffleVectorExprClass:\r
- case Expr::StmtExprClass:\r
- case Expr::UnaryTypeTraitExprClass:\r
- case Expr::BinaryTypeTraitExprClass:\r
- case Expr::TypeTraitExprClass:\r
- case Expr::ArrayTypeTraitExprClass:\r
- case Expr::ExpressionTraitExprClass:\r
- case Expr::VAArgExprClass:\r
- case Expr::CXXUuidofExprClass:\r
- case Expr::CUDAKernelCallExprClass:\r
- case Expr::AsTypeExprClass:\r
- case Expr::PseudoObjectExprClass:\r
- case Expr::AtomicExprClass:\r
- {\r
- // As bad as this diagnostic is, it's better than crashing.\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot yet mangle expression type %0");\r
- Diags.Report(E->getExprLoc(), DiagID)\r
- << E->getStmtClassName() << E->getSourceRange();\r
- break;\r
- }\r
-\r
- // Even gcc-4.5 doesn't mangle this.\r
- case Expr::BinaryConditionalOperatorClass: {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID =\r
- Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "?: operator with omitted middle operand cannot be mangled");\r
- Diags.Report(E->getExprLoc(), DiagID)\r
- << E->getStmtClassName() << E->getSourceRange();\r
- break;\r
- }\r
-\r
- // These are used for internal purposes and cannot be meaningfully mangled.\r
- case Expr::OpaqueValueExprClass:\r
- llvm_unreachable("cannot mangle opaque value; mangling wrong thing?");\r
-\r
- case Expr::InitListExprClass: {\r
- // Proposal by Jason Merrill, 2012-01-03\r
- Out << "il";\r
- const InitListExpr *InitList = cast<InitListExpr>(E);\r
- for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)\r
- mangleExpression(InitList->getInit(i));\r
- Out << "E";\r
- break;\r
- }\r
-\r
- case Expr::CXXDefaultArgExprClass:\r
- mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity);\r
- break;\r
-\r
- case Expr::SubstNonTypeTemplateParmExprClass:\r
- mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),\r
- Arity);\r
- break;\r
-\r
- case Expr::UserDefinedLiteralClass:\r
- // We follow g++'s approach of mangling a UDL as a call to the literal\r
- // operator.\r
- case Expr::CXXMemberCallExprClass: // fallthrough\r
- case Expr::CallExprClass: {\r
- const CallExpr *CE = cast<CallExpr>(E);\r
-\r
- // <expression> ::= cp <simple-id> <expression>* E\r
- // We use this mangling only when the call would use ADL except\r
- // for being parenthesized. Per discussion with David\r
- // Vandervoorde, 2011.04.25.\r
- if (isParenthesizedADLCallee(CE)) {\r
- Out << "cp";\r
- // The callee here is a parenthesized UnresolvedLookupExpr with\r
- // no qualifier and should always get mangled as a <simple-id>\r
- // anyway.\r
-\r
- // <expression> ::= cl <expression>* E\r
- } else {\r
- Out << "cl";\r
- }\r
-\r
- mangleExpression(CE->getCallee(), CE->getNumArgs());\r
- for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I)\r
- mangleExpression(CE->getArg(I));\r
- Out << 'E';\r
- break;\r
- }\r
-\r
- case Expr::CXXNewExprClass: {\r
- const CXXNewExpr *New = cast<CXXNewExpr>(E);\r
- if (New->isGlobalNew()) Out << "gs";\r
- Out << (New->isArray() ? "na" : "nw");\r
- for (CXXNewExpr::const_arg_iterator I = New->placement_arg_begin(),\r
- E = New->placement_arg_end(); I != E; ++I)\r
- mangleExpression(*I);\r
- Out << '_';\r
- mangleType(New->getAllocatedType());\r
- if (New->hasInitializer()) {\r
- // Proposal by Jason Merrill, 2012-01-03\r
- if (New->getInitializationStyle() == CXXNewExpr::ListInit)\r
- Out << "il";\r
- else\r
- Out << "pi";\r
- const Expr *Init = New->getInitializer();\r
- if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) {\r
- // Directly inline the initializers.\r
- for (CXXConstructExpr::const_arg_iterator I = CCE->arg_begin(),\r
- E = CCE->arg_end();\r
- I != E; ++I)\r
- mangleExpression(*I);\r
- } else if (const ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) {\r
- for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i)\r
- mangleExpression(PLE->getExpr(i));\r
- } else if (New->getInitializationStyle() == CXXNewExpr::ListInit &&\r
- isa<InitListExpr>(Init)) {\r
- // Only take InitListExprs apart for list-initialization.\r
- const InitListExpr *InitList = cast<InitListExpr>(Init);\r
- for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)\r
- mangleExpression(InitList->getInit(i));\r
- } else\r
- mangleExpression(Init);\r
- }\r
- Out << 'E';\r
- break;\r
- }\r
-\r
- case Expr::MemberExprClass: {\r
- const MemberExpr *ME = cast<MemberExpr>(E);\r
- mangleMemberExpr(ME->getBase(), ME->isArrow(),\r
- ME->getQualifier(), 0, ME->getMemberDecl()->getDeclName(),\r
- Arity);\r
- break;\r
- }\r
-\r
- case Expr::UnresolvedMemberExprClass: {\r
- const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);\r
- mangleMemberExpr(ME->getBase(), ME->isArrow(),\r
- ME->getQualifier(), 0, ME->getMemberName(),\r
- Arity);\r
- if (ME->hasExplicitTemplateArgs())\r
- mangleTemplateArgs(ME->getExplicitTemplateArgs());\r
- break;\r
- }\r
-\r
- case Expr::CXXDependentScopeMemberExprClass: {\r
- const CXXDependentScopeMemberExpr *ME\r
- = cast<CXXDependentScopeMemberExpr>(E);\r
- mangleMemberExpr(ME->getBase(), ME->isArrow(),\r
- ME->getQualifier(), ME->getFirstQualifierFoundInScope(),\r
- ME->getMember(), Arity);\r
- if (ME->hasExplicitTemplateArgs())\r
- mangleTemplateArgs(ME->getExplicitTemplateArgs());\r
- break;\r
- }\r
-\r
- case Expr::UnresolvedLookupExprClass: {\r
- const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);\r
- mangleUnresolvedName(ULE->getQualifier(), 0, ULE->getName(), Arity);\r
-\r
- // All the <unresolved-name> productions end in a\r
- // base-unresolved-name, where <template-args> are just tacked\r
- // onto the end.\r
- if (ULE->hasExplicitTemplateArgs())\r
- mangleTemplateArgs(ULE->getExplicitTemplateArgs());\r
- break;\r
- }\r
-\r
- case Expr::CXXUnresolvedConstructExprClass: {\r
- const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);\r
- unsigned N = CE->arg_size();\r
-\r
- Out << "cv";\r
- mangleType(CE->getType());\r
- if (N != 1) Out << '_';\r
- for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));\r
- if (N != 1) Out << 'E';\r
- break;\r
- }\r
-\r
- case Expr::CXXTemporaryObjectExprClass:\r
- case Expr::CXXConstructExprClass: {\r
- const CXXConstructExpr *CE = cast<CXXConstructExpr>(E);\r
- unsigned N = CE->getNumArgs();\r
-\r
- // Proposal by Jason Merrill, 2012-01-03\r
- if (CE->isListInitialization())\r
- Out << "tl";\r
- else\r
- Out << "cv";\r
- mangleType(CE->getType());\r
- if (N != 1) Out << '_';\r
- for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));\r
- if (N != 1) Out << 'E';\r
- break;\r
- }\r
-\r
- case Expr::CXXScalarValueInitExprClass:\r
- Out <<"cv";\r
- mangleType(E->getType());\r
- Out <<"_E";\r
- break;\r
-\r
- case Expr::CXXNoexceptExprClass:\r
- Out << "nx";\r
- mangleExpression(cast<CXXNoexceptExpr>(E)->getOperand());\r
- break;\r
-\r
- case Expr::UnaryExprOrTypeTraitExprClass: {\r
- const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E);\r
- \r
- if (!SAE->isInstantiationDependent()) {\r
- // Itanium C++ ABI:\r
- // If the operand of a sizeof or alignof operator is not \r
- // instantiation-dependent it is encoded as an integer literal \r
- // reflecting the result of the operator.\r
- //\r
- // If the result of the operator is implicitly converted to a known \r
- // integer type, that type is used for the literal; otherwise, the type \r
- // of std::size_t or std::ptrdiff_t is used.\r
- QualType T = (ImplicitlyConvertedToType.isNull() || \r
- !ImplicitlyConvertedToType->isIntegerType())? SAE->getType()\r
- : ImplicitlyConvertedToType;\r
- llvm::APSInt V = SAE->EvaluateKnownConstInt(Context.getASTContext());\r
- mangleIntegerLiteral(T, V);\r
- break;\r
- }\r
- \r
- switch(SAE->getKind()) {\r
- case UETT_SizeOf:\r
- Out << 's';\r
- break;\r
- case UETT_AlignOf:\r
- Out << 'a';\r
- break;\r
- case UETT_VecStep:\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot yet mangle vec_step expression");\r
- Diags.Report(DiagID);\r
- return;\r
- }\r
- if (SAE->isArgumentType()) {\r
- Out << 't';\r
- mangleType(SAE->getArgumentType());\r
- } else {\r
- Out << 'z';\r
- mangleExpression(SAE->getArgumentExpr());\r
- }\r
- break;\r
- }\r
-\r
- case Expr::CXXThrowExprClass: {\r
- const CXXThrowExpr *TE = cast<CXXThrowExpr>(E);\r
-\r
- // Proposal from David Vandervoorde, 2010.06.30\r
- if (TE->getSubExpr()) {\r
- Out << "tw";\r
- mangleExpression(TE->getSubExpr());\r
- } else {\r
- Out << "tr";\r
- }\r
- break;\r
- }\r
-\r
- case Expr::CXXTypeidExprClass: {\r
- const CXXTypeidExpr *TIE = cast<CXXTypeidExpr>(E);\r
-\r
- // Proposal from David Vandervoorde, 2010.06.30\r
- if (TIE->isTypeOperand()) {\r
- Out << "ti";\r
- mangleType(TIE->getTypeOperand());\r
- } else {\r
- Out << "te";\r
- mangleExpression(TIE->getExprOperand());\r
- }\r
- break;\r
- }\r
-\r
- case Expr::CXXDeleteExprClass: {\r
- const CXXDeleteExpr *DE = cast<CXXDeleteExpr>(E);\r
-\r
- // Proposal from David Vandervoorde, 2010.06.30\r
- if (DE->isGlobalDelete()) Out << "gs";\r
- Out << (DE->isArrayForm() ? "da" : "dl");\r
- mangleExpression(DE->getArgument());\r
- break;\r
- }\r
-\r
- case Expr::UnaryOperatorClass: {\r
- const UnaryOperator *UO = cast<UnaryOperator>(E);\r
- mangleOperatorName(UnaryOperator::getOverloadedOperator(UO->getOpcode()),\r
- /*Arity=*/1);\r
- mangleExpression(UO->getSubExpr());\r
- break;\r
- }\r
-\r
- case Expr::ArraySubscriptExprClass: {\r
- const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(E);\r
-\r
- // Array subscript is treated as a syntactically weird form of\r
- // binary operator.\r
- Out << "ix";\r
- mangleExpression(AE->getLHS());\r
- mangleExpression(AE->getRHS());\r
- break;\r
- }\r
-\r
- case Expr::CompoundAssignOperatorClass: // fallthrough\r
- case Expr::BinaryOperatorClass: {\r
- const BinaryOperator *BO = cast<BinaryOperator>(E);\r
- if (BO->getOpcode() == BO_PtrMemD)\r
- Out << "ds";\r
- else\r
- mangleOperatorName(BinaryOperator::getOverloadedOperator(BO->getOpcode()),\r
- /*Arity=*/2);\r
- mangleExpression(BO->getLHS());\r
- mangleExpression(BO->getRHS());\r
- break;\r
- }\r
-\r
- case Expr::ConditionalOperatorClass: {\r
- const ConditionalOperator *CO = cast<ConditionalOperator>(E);\r
- mangleOperatorName(OO_Conditional, /*Arity=*/3);\r
- mangleExpression(CO->getCond());\r
- mangleExpression(CO->getLHS(), Arity);\r
- mangleExpression(CO->getRHS(), Arity);\r
- break;\r
- }\r
-\r
- case Expr::ImplicitCastExprClass: {\r
- ImplicitlyConvertedToType = E->getType();\r
- E = cast<ImplicitCastExpr>(E)->getSubExpr();\r
- goto recurse;\r
- }\r
- \r
- case Expr::ObjCBridgedCastExprClass: {\r
- // Mangle ownership casts as a vendor extended operator __bridge, \r
- // __bridge_transfer, or __bridge_retain.\r
- StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName();\r
- Out << "v1U" << Kind.size() << Kind;\r
- }\r
- // Fall through to mangle the cast itself.\r
- \r
- case Expr::CStyleCastExprClass:\r
- case Expr::CXXStaticCastExprClass:\r
- case Expr::CXXDynamicCastExprClass:\r
- case Expr::CXXReinterpretCastExprClass:\r
- case Expr::CXXConstCastExprClass:\r
- case Expr::CXXFunctionalCastExprClass: {\r
- const ExplicitCastExpr *ECE = cast<ExplicitCastExpr>(E);\r
- Out << "cv";\r
- mangleType(ECE->getType());\r
- mangleExpression(ECE->getSubExpr());\r
- break;\r
- }\r
-\r
- case Expr::CXXOperatorCallExprClass: {\r
- const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);\r
- unsigned NumArgs = CE->getNumArgs();\r
- mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs);\r
- // Mangle the arguments.\r
- for (unsigned i = 0; i != NumArgs; ++i)\r
- mangleExpression(CE->getArg(i));\r
- break;\r
- }\r
-\r
- case Expr::ParenExprClass:\r
- mangleExpression(cast<ParenExpr>(E)->getSubExpr(), Arity);\r
- break;\r
-\r
- case Expr::DeclRefExprClass: {\r
- const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl();\r
-\r
- switch (D->getKind()) {\r
- default:\r
- // <expr-primary> ::= L <mangled-name> E # external name\r
- Out << 'L';\r
- mangle(D, "_Z");\r
- Out << 'E';\r
- break;\r
-\r
- case Decl::ParmVar:\r
- mangleFunctionParam(cast<ParmVarDecl>(D));\r
- break;\r
-\r
- case Decl::EnumConstant: {\r
- const EnumConstantDecl *ED = cast<EnumConstantDecl>(D);\r
- mangleIntegerLiteral(ED->getType(), ED->getInitVal());\r
- break;\r
- }\r
-\r
- case Decl::NonTypeTemplateParm: {\r
- const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);\r
- mangleTemplateParameter(PD->getIndex());\r
- break;\r
- }\r
-\r
- }\r
-\r
- break;\r
- }\r
-\r
- case Expr::SubstNonTypeTemplateParmPackExprClass:\r
- // FIXME: not clear how to mangle this!\r
- // template <unsigned N...> class A {\r
- // template <class U...> void foo(U (&x)[N]...);\r
- // };\r
- Out << "_SUBSTPACK_";\r
- break;\r
-\r
- case Expr::FunctionParmPackExprClass: {\r
- // FIXME: not clear how to mangle this!\r
- const FunctionParmPackExpr *FPPE = cast<FunctionParmPackExpr>(E);\r
- Out << "v110_SUBSTPACK";\r
- mangleFunctionParam(FPPE->getParameterPack());\r
- break;\r
- }\r
-\r
- case Expr::DependentScopeDeclRefExprClass: {\r
- const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);\r
- mangleUnresolvedName(DRE->getQualifier(), 0, DRE->getDeclName(), Arity);\r
-\r
- // All the <unresolved-name> productions end in a\r
- // base-unresolved-name, where <template-args> are just tacked\r
- // onto the end.\r
- if (DRE->hasExplicitTemplateArgs())\r
- mangleTemplateArgs(DRE->getExplicitTemplateArgs());\r
- break;\r
- }\r
-\r
- case Expr::CXXBindTemporaryExprClass:\r
- mangleExpression(cast<CXXBindTemporaryExpr>(E)->getSubExpr());\r
- break;\r
-\r
- case Expr::ExprWithCleanupsClass:\r
- mangleExpression(cast<ExprWithCleanups>(E)->getSubExpr(), Arity);\r
- break;\r
-\r
- case Expr::FloatingLiteralClass: {\r
- const FloatingLiteral *FL = cast<FloatingLiteral>(E);\r
- Out << 'L';\r
- mangleType(FL->getType());\r
- mangleFloat(FL->getValue());\r
- Out << 'E';\r
- break;\r
- }\r
-\r
- case Expr::CharacterLiteralClass:\r
- Out << 'L';\r
- mangleType(E->getType());\r
- Out << cast<CharacterLiteral>(E)->getValue();\r
- Out << 'E';\r
- break;\r
-\r
- // FIXME. __objc_yes/__objc_no are mangled same as true/false\r
- case Expr::ObjCBoolLiteralExprClass:\r
- Out << "Lb";\r
- Out << (cast<ObjCBoolLiteralExpr>(E)->getValue() ? '1' : '0');\r
- Out << 'E';\r
- break;\r
- \r
- case Expr::CXXBoolLiteralExprClass:\r
- Out << "Lb";\r
- Out << (cast<CXXBoolLiteralExpr>(E)->getValue() ? '1' : '0');\r
- Out << 'E';\r
- break;\r
-\r
- case Expr::IntegerLiteralClass: {\r
- llvm::APSInt Value(cast<IntegerLiteral>(E)->getValue());\r
- if (E->getType()->isSignedIntegerType())\r
- Value.setIsSigned(true);\r
- mangleIntegerLiteral(E->getType(), Value);\r
- break;\r
- }\r
-\r
- case Expr::ImaginaryLiteralClass: {\r
- const ImaginaryLiteral *IE = cast<ImaginaryLiteral>(E);\r
- // Mangle as if a complex literal.\r
- // Proposal from David Vandevoorde, 2010.06.30.\r
- Out << 'L';\r
- mangleType(E->getType());\r
- if (const FloatingLiteral *Imag =\r
- dyn_cast<FloatingLiteral>(IE->getSubExpr())) {\r
- // Mangle a floating-point zero of the appropriate type.\r
- mangleFloat(llvm::APFloat(Imag->getValue().getSemantics()));\r
- Out << '_';\r
- mangleFloat(Imag->getValue());\r
- } else {\r
- Out << "0_";\r
- llvm::APSInt Value(cast<IntegerLiteral>(IE->getSubExpr())->getValue());\r
- if (IE->getSubExpr()->getType()->isSignedIntegerType())\r
- Value.setIsSigned(true);\r
- mangleNumber(Value);\r
- }\r
- Out << 'E';\r
- break;\r
- }\r
-\r
- case Expr::StringLiteralClass: {\r
- // Revised proposal from David Vandervoorde, 2010.07.15.\r
- Out << 'L';\r
- assert(isa<ConstantArrayType>(E->getType()));\r
- mangleType(E->getType());\r
- Out << 'E';\r
- break;\r
- }\r
-\r
- case Expr::GNUNullExprClass:\r
- // FIXME: should this really be mangled the same as nullptr?\r
- // fallthrough\r
-\r
- case Expr::CXXNullPtrLiteralExprClass: {\r
- // Proposal from David Vandervoorde, 2010.06.30, as\r
- // modified by ABI list discussion.\r
- Out << "LDnE";\r
- break;\r
- }\r
- \r
- case Expr::PackExpansionExprClass:\r
- Out << "sp";\r
- mangleExpression(cast<PackExpansionExpr>(E)->getPattern());\r
- break;\r
- \r
- case Expr::SizeOfPackExprClass: {\r
- Out << "sZ";\r
- const NamedDecl *Pack = cast<SizeOfPackExpr>(E)->getPack();\r
- if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack))\r
- mangleTemplateParameter(TTP->getIndex());\r
- else if (const NonTypeTemplateParmDecl *NTTP\r
- = dyn_cast<NonTypeTemplateParmDecl>(Pack))\r
- mangleTemplateParameter(NTTP->getIndex());\r
- else if (const TemplateTemplateParmDecl *TempTP\r
- = dyn_cast<TemplateTemplateParmDecl>(Pack))\r
- mangleTemplateParameter(TempTP->getIndex());\r
- else\r
- mangleFunctionParam(cast<ParmVarDecl>(Pack));\r
- break;\r
- }\r
- \r
- case Expr::MaterializeTemporaryExprClass: {\r
- mangleExpression(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr());\r
- break;\r
- }\r
- \r
- case Expr::CXXThisExprClass:\r
- Out << "fpT";\r
- break;\r
- }\r
-}\r
-\r
-/// Mangle an expression which refers to a parameter variable.\r
-///\r
-/// <expression> ::= <function-param>\r
-/// <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, I == 0\r
-/// <function-param> ::= fp <top-level CV-qualifiers>\r
-/// <parameter-2 non-negative number> _ # L == 0, I > 0\r
-/// <function-param> ::= fL <L-1 non-negative number>\r
-/// p <top-level CV-qualifiers> _ # L > 0, I == 0\r
-/// <function-param> ::= fL <L-1 non-negative number>\r
-/// p <top-level CV-qualifiers>\r
-/// <I-1 non-negative number> _ # L > 0, I > 0\r
-///\r
-/// L is the nesting depth of the parameter, defined as 1 if the\r
-/// parameter comes from the innermost function prototype scope\r
-/// enclosing the current context, 2 if from the next enclosing\r
-/// function prototype scope, and so on, with one special case: if\r
-/// we've processed the full parameter clause for the innermost\r
-/// function type, then L is one less. This definition conveniently\r
-/// makes it irrelevant whether a function's result type was written\r
-/// trailing or leading, but is otherwise overly complicated; the\r
-/// numbering was first designed without considering references to\r
-/// parameter in locations other than return types, and then the\r
-/// mangling had to be generalized without changing the existing\r
-/// manglings.\r
-///\r
-/// I is the zero-based index of the parameter within its parameter\r
-/// declaration clause. Note that the original ABI document describes\r
-/// this using 1-based ordinals.\r
-void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) {\r
- unsigned parmDepth = parm->getFunctionScopeDepth();\r
- unsigned parmIndex = parm->getFunctionScopeIndex();\r
-\r
- // Compute 'L'.\r
- // parmDepth does not include the declaring function prototype.\r
- // FunctionTypeDepth does account for that.\r
- assert(parmDepth < FunctionTypeDepth.getDepth());\r
- unsigned nestingDepth = FunctionTypeDepth.getDepth() - parmDepth;\r
- if (FunctionTypeDepth.isInResultType())\r
- nestingDepth--;\r
-\r
- if (nestingDepth == 0) {\r
- Out << "fp";\r
- } else {\r
- Out << "fL" << (nestingDepth - 1) << 'p';\r
- }\r
-\r
- // Top-level qualifiers. We don't have to worry about arrays here,\r
- // because parameters declared as arrays should already have been\r
- // transformed to have pointer type. FIXME: apparently these don't\r
- // get mangled if used as an rvalue of a known non-class type?\r
- assert(!parm->getType()->isArrayType()\r
- && "parameter's type is still an array type?");\r
- mangleQualifiers(parm->getType().getQualifiers());\r
-\r
- // Parameter index.\r
- if (parmIndex != 0) {\r
- Out << (parmIndex - 1);\r
- }\r
- Out << '_';\r
-}\r
-\r
-void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {\r
- // <ctor-dtor-name> ::= C1 # complete object constructor\r
- // ::= C2 # base object constructor\r
- // ::= C3 # complete object allocating constructor\r
- //\r
- switch (T) {\r
- case Ctor_Complete:\r
- Out << "C1";\r
- break;\r
- case Ctor_Base:\r
- Out << "C2";\r
- break;\r
- case Ctor_CompleteAllocating:\r
- Out << "C3";\r
- break;\r
- }\r
-}\r
-\r
-void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {\r
- // <ctor-dtor-name> ::= D0 # deleting destructor\r
- // ::= D1 # complete object destructor\r
- // ::= D2 # base object destructor\r
- //\r
- switch (T) {\r
- case Dtor_Deleting:\r
- Out << "D0";\r
- break;\r
- case Dtor_Complete:\r
- Out << "D1";\r
- break;\r
- case Dtor_Base:\r
- Out << "D2";\r
- break;\r
- }\r
-}\r
-\r
-void CXXNameMangler::mangleTemplateArgs(\r
- const ASTTemplateArgumentListInfo &TemplateArgs) {\r
- // <template-args> ::= I <template-arg>+ E\r
- Out << 'I';\r
- for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i)\r
- mangleTemplateArg(TemplateArgs.getTemplateArgs()[i].getArgument());\r
- Out << 'E';\r
-}\r
-\r
-void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentList &AL) {\r
- // <template-args> ::= I <template-arg>+ E\r
- Out << 'I';\r
- for (unsigned i = 0, e = AL.size(); i != e; ++i)\r
- mangleTemplateArg(AL[i]);\r
- Out << 'E';\r
-}\r
-\r
-void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs,\r
- unsigned NumTemplateArgs) {\r
- // <template-args> ::= I <template-arg>+ E\r
- Out << 'I';\r
- for (unsigned i = 0; i != NumTemplateArgs; ++i)\r
- mangleTemplateArg(TemplateArgs[i]);\r
- Out << 'E';\r
-}\r
-\r
-void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {\r
- // <template-arg> ::= <type> # type or template\r
- // ::= X <expression> E # expression\r
- // ::= <expr-primary> # simple expressions\r
- // ::= J <template-arg>* E # argument pack\r
- // ::= sp <expression> # pack expansion of (C++0x) \r
- if (!A.isInstantiationDependent() || A.isDependent())\r
- A = Context.getASTContext().getCanonicalTemplateArgument(A);\r
- \r
- switch (A.getKind()) {\r
- case TemplateArgument::Null:\r
- llvm_unreachable("Cannot mangle NULL template argument");\r
- \r
- case TemplateArgument::Type:\r
- mangleType(A.getAsType());\r
- break;\r
- case TemplateArgument::Template:\r
- // This is mangled as <type>.\r
- mangleType(A.getAsTemplate());\r
- break;\r
- case TemplateArgument::TemplateExpansion:\r
- // <type> ::= Dp <type> # pack expansion (C++0x)\r
- Out << "Dp";\r
- mangleType(A.getAsTemplateOrTemplatePattern());\r
- break;\r
- case TemplateArgument::Expression: {\r
- // It's possible to end up with a DeclRefExpr here in certain\r
- // dependent cases, in which case we should mangle as a\r
- // declaration.\r
- const Expr *E = A.getAsExpr()->IgnoreParens();\r
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {\r
- const ValueDecl *D = DRE->getDecl();\r
- if (isa<VarDecl>(D) || isa<FunctionDecl>(D)) {\r
- Out << "L";\r
- mangle(D, "_Z");\r
- Out << 'E';\r
- break;\r
- }\r
- }\r
- \r
- Out << 'X';\r
- mangleExpression(E);\r
- Out << 'E';\r
- break;\r
- }\r
- case TemplateArgument::Integral:\r
- mangleIntegerLiteral(A.getIntegralType(), A.getAsIntegral());\r
- break;\r
- case TemplateArgument::Declaration: {\r
- // <expr-primary> ::= L <mangled-name> E # external name\r
- // Clang produces AST's where pointer-to-member-function expressions\r
- // and pointer-to-function expressions are represented as a declaration not\r
- // an expression. We compensate for it here to produce the correct mangling.\r
- ValueDecl *D = A.getAsDecl();\r
- bool compensateMangling = !A.isDeclForReferenceParam();\r
- if (compensateMangling) {\r
- Out << 'X';\r
- mangleOperatorName(OO_Amp, 1);\r
- }\r
-\r
- Out << 'L';\r
- // References to external entities use the mangled name; if the name would\r
- // not normally be manged then mangle it as unqualified.\r
- //\r
- // FIXME: The ABI specifies that external names here should have _Z, but\r
- // gcc leaves this off.\r
- if (compensateMangling)\r
- mangle(D, "_Z");\r
- else\r
- mangle(D, "Z");\r
- Out << 'E';\r
-\r
- if (compensateMangling)\r
- Out << 'E';\r
-\r
- break;\r
- }\r
- case TemplateArgument::NullPtr: {\r
- // <expr-primary> ::= L <type> 0 E\r
- Out << 'L';\r
- mangleType(A.getNullPtrType());\r
- Out << "0E";\r
- break;\r
- }\r
- case TemplateArgument::Pack: {\r
- // Note: proposal by Mike Herrick on 12/20/10\r
- Out << 'J';\r
- for (TemplateArgument::pack_iterator PA = A.pack_begin(), \r
- PAEnd = A.pack_end();\r
- PA != PAEnd; ++PA)\r
- mangleTemplateArg(*PA);\r
- Out << 'E';\r
- }\r
- }\r
-}\r
-\r
-void CXXNameMangler::mangleTemplateParameter(unsigned Index) {\r
- // <template-param> ::= T_ # first template parameter\r
- // ::= T <parameter-2 non-negative number> _\r
- if (Index == 0)\r
- Out << "T_";\r
- else\r
- Out << 'T' << (Index - 1) << '_';\r
-}\r
-\r
-void CXXNameMangler::mangleExistingSubstitution(QualType type) {\r
- bool result = mangleSubstitution(type);\r
- assert(result && "no existing substitution for type");\r
- (void) result;\r
-}\r
-\r
-void CXXNameMangler::mangleExistingSubstitution(TemplateName tname) {\r
- bool result = mangleSubstitution(tname);\r
- assert(result && "no existing substitution for template name");\r
- (void) result;\r
-}\r
-\r
-// <substitution> ::= S <seq-id> _\r
-// ::= S_\r
-bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {\r
- // Try one of the standard substitutions first.\r
- if (mangleStandardSubstitution(ND))\r
- return true;\r
-\r
- ND = cast<NamedDecl>(ND->getCanonicalDecl());\r
- return mangleSubstitution(reinterpret_cast<uintptr_t>(ND));\r
-}\r
-\r
-/// \brief Determine whether the given type has any qualifiers that are\r
-/// relevant for substitutions.\r
-static bool hasMangledSubstitutionQualifiers(QualType T) {\r
- Qualifiers Qs = T.getQualifiers();\r
- return Qs.getCVRQualifiers() || Qs.hasAddressSpace();\r
-}\r
-\r
-bool CXXNameMangler::mangleSubstitution(QualType T) {\r
- if (!hasMangledSubstitutionQualifiers(T)) {\r
- if (const RecordType *RT = T->getAs<RecordType>())\r
- return mangleSubstitution(RT->getDecl());\r
- }\r
-\r
- uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());\r
-\r
- return mangleSubstitution(TypePtr);\r
-}\r
-\r
-bool CXXNameMangler::mangleSubstitution(TemplateName Template) {\r
- if (TemplateDecl *TD = Template.getAsTemplateDecl())\r
- return mangleSubstitution(TD);\r
- \r
- Template = Context.getASTContext().getCanonicalTemplateName(Template);\r
- return mangleSubstitution(\r
- reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));\r
-}\r
-\r
-bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) {\r
- llvm::DenseMap<uintptr_t, unsigned>::iterator I = Substitutions.find(Ptr);\r
- if (I == Substitutions.end())\r
- return false;\r
-\r
- unsigned SeqID = I->second;\r
- if (SeqID == 0)\r
- Out << "S_";\r
- else {\r
- SeqID--;\r
-\r
- // <seq-id> is encoded in base-36, using digits and upper case letters.\r
- char Buffer[10];\r
- char *BufferPtr = llvm::array_endof(Buffer);\r
-\r
- if (SeqID == 0) *--BufferPtr = '0';\r
-\r
- while (SeqID) {\r
- assert(BufferPtr > Buffer && "Buffer overflow!");\r
-\r
- char c = static_cast<char>(SeqID % 36);\r
-\r
- *--BufferPtr = (c < 10 ? '0' + c : 'A' + c - 10);\r
- SeqID /= 36;\r
- }\r
-\r
- Out << 'S'\r
- << StringRef(BufferPtr, llvm::array_endof(Buffer)-BufferPtr)\r
- << '_';\r
- }\r
-\r
- return true;\r
-}\r
-\r
-static bool isCharType(QualType T) {\r
- if (T.isNull())\r
- return false;\r
-\r
- return T->isSpecificBuiltinType(BuiltinType::Char_S) ||\r
- T->isSpecificBuiltinType(BuiltinType::Char_U);\r
-}\r
-\r
-/// isCharSpecialization - Returns whether a given type is a template\r
-/// specialization of a given name with a single argument of type char.\r
-static bool isCharSpecialization(QualType T, const char *Name) {\r
- if (T.isNull())\r
- return false;\r
-\r
- const RecordType *RT = T->getAs<RecordType>();\r
- if (!RT)\r
- return false;\r
-\r
- const ClassTemplateSpecializationDecl *SD =\r
- dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());\r
- if (!SD)\r
- return false;\r
-\r
- if (!isStdNamespace(getEffectiveDeclContext(SD)))\r
- return false;\r
-\r
- const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();\r
- if (TemplateArgs.size() != 1)\r
- return false;\r
-\r
- if (!isCharType(TemplateArgs[0].getAsType()))\r
- return false;\r
-\r
- return SD->getIdentifier()->getName() == Name;\r
-}\r
-\r
-template <std::size_t StrLen>\r
-static bool isStreamCharSpecialization(const ClassTemplateSpecializationDecl*SD,\r
- const char (&Str)[StrLen]) {\r
- if (!SD->getIdentifier()->isStr(Str))\r
- return false;\r
-\r
- const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();\r
- if (TemplateArgs.size() != 2)\r
- return false;\r
-\r
- if (!isCharType(TemplateArgs[0].getAsType()))\r
- return false;\r
-\r
- if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))\r
- return false;\r
-\r
- return true;\r
-}\r
-\r
-bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {\r
- // <substitution> ::= St # ::std::\r
- if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {\r
- if (isStd(NS)) {\r
- Out << "St";\r
- return true;\r
- }\r
- }\r
-\r
- if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {\r
- if (!isStdNamespace(getEffectiveDeclContext(TD)))\r
- return false;\r
-\r
- // <substitution> ::= Sa # ::std::allocator\r
- if (TD->getIdentifier()->isStr("allocator")) {\r
- Out << "Sa";\r
- return true;\r
- }\r
-\r
- // <<substitution> ::= Sb # ::std::basic_string\r
- if (TD->getIdentifier()->isStr("basic_string")) {\r
- Out << "Sb";\r
- return true;\r
- }\r
- }\r
-\r
- if (const ClassTemplateSpecializationDecl *SD =\r
- dyn_cast<ClassTemplateSpecializationDecl>(ND)) {\r
- if (!isStdNamespace(getEffectiveDeclContext(SD)))\r
- return false;\r
-\r
- // <substitution> ::= Ss # ::std::basic_string<char,\r
- // ::std::char_traits<char>,\r
- // ::std::allocator<char> >\r
- if (SD->getIdentifier()->isStr("basic_string")) {\r
- const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();\r
-\r
- if (TemplateArgs.size() != 3)\r
- return false;\r
-\r
- if (!isCharType(TemplateArgs[0].getAsType()))\r
- return false;\r
-\r
- if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))\r
- return false;\r
-\r
- if (!isCharSpecialization(TemplateArgs[2].getAsType(), "allocator"))\r
- return false;\r
-\r
- Out << "Ss";\r
- return true;\r
- }\r
-\r
- // <substitution> ::= Si # ::std::basic_istream<char,\r
- // ::std::char_traits<char> >\r
- if (isStreamCharSpecialization(SD, "basic_istream")) {\r
- Out << "Si";\r
- return true;\r
- }\r
-\r
- // <substitution> ::= So # ::std::basic_ostream<char,\r
- // ::std::char_traits<char> >\r
- if (isStreamCharSpecialization(SD, "basic_ostream")) {\r
- Out << "So";\r
- return true;\r
- }\r
-\r
- // <substitution> ::= Sd # ::std::basic_iostream<char,\r
- // ::std::char_traits<char> >\r
- if (isStreamCharSpecialization(SD, "basic_iostream")) {\r
- Out << "Sd";\r
- return true;\r
- }\r
- }\r
- return false;\r
-}\r
-\r
-void CXXNameMangler::addSubstitution(QualType T) {\r
- if (!hasMangledSubstitutionQualifiers(T)) {\r
- if (const RecordType *RT = T->getAs<RecordType>()) {\r
- addSubstitution(RT->getDecl());\r
- return;\r
- }\r
- }\r
-\r
- uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());\r
- addSubstitution(TypePtr);\r
-}\r
-\r
-void CXXNameMangler::addSubstitution(TemplateName Template) {\r
- if (TemplateDecl *TD = Template.getAsTemplateDecl())\r
- return addSubstitution(TD);\r
- \r
- Template = Context.getASTContext().getCanonicalTemplateName(Template);\r
- addSubstitution(reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));\r
-}\r
-\r
-void CXXNameMangler::addSubstitution(uintptr_t Ptr) {\r
- assert(!Substitutions.count(Ptr) && "Substitution already exists!");\r
- Substitutions[Ptr] = SeqID++;\r
-}\r
-\r
-//\r
-\r
-/// \brief Mangles the name of the declaration D and emits that name to the\r
-/// given output stream.\r
-///\r
-/// If the declaration D requires a mangled name, this routine will emit that\r
-/// mangled name to \p os and return true. Otherwise, \p os will be unchanged\r
-/// and this routine will return false. In this case, the caller should just\r
-/// emit the identifier of the declaration (\c D->getIdentifier()) as its\r
-/// name.\r
-void ItaniumMangleContext::mangleName(const NamedDecl *D,\r
- raw_ostream &Out) {\r
- assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&\r
- "Invalid mangleName() call, argument is not a variable or function!");\r
- assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&\r
- "Invalid mangleName() call on 'structor decl!");\r
-\r
- PrettyStackTraceDecl CrashInfo(D, SourceLocation(),\r
- getASTContext().getSourceManager(),\r
- "Mangling declaration");\r
-\r
- CXXNameMangler Mangler(*this, Out, D);\r
- return Mangler.mangle(D);\r
-}\r
-\r
-void ItaniumMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,\r
- CXXCtorType Type,\r
- raw_ostream &Out) {\r
- CXXNameMangler Mangler(*this, Out, D, Type);\r
- Mangler.mangle(D);\r
-}\r
-\r
-void ItaniumMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,\r
- CXXDtorType Type,\r
- raw_ostream &Out) {\r
- CXXNameMangler Mangler(*this, Out, D, Type);\r
- Mangler.mangle(D);\r
-}\r
-\r
-void ItaniumMangleContext::mangleThunk(const CXXMethodDecl *MD,\r
- const ThunkInfo &Thunk,\r
- raw_ostream &Out) {\r
- // <special-name> ::= T <call-offset> <base encoding>\r
- // # base is the nominal target function of thunk\r
- // <special-name> ::= Tc <call-offset> <call-offset> <base encoding>\r
- // # base is the nominal target function of thunk\r
- // # first call-offset is 'this' adjustment\r
- // # second call-offset is result adjustment\r
- \r
- assert(!isa<CXXDestructorDecl>(MD) &&\r
- "Use mangleCXXDtor for destructor decls!");\r
- CXXNameMangler Mangler(*this, Out);\r
- Mangler.getStream() << "_ZT";\r
- if (!Thunk.Return.isEmpty())\r
- Mangler.getStream() << 'c';\r
- \r
- // Mangle the 'this' pointer adjustment.\r
- Mangler.mangleCallOffset(Thunk.This.NonVirtual, Thunk.This.VCallOffsetOffset);\r
- \r
- // Mangle the return pointer adjustment if there is one.\r
- if (!Thunk.Return.isEmpty())\r
- Mangler.mangleCallOffset(Thunk.Return.NonVirtual,\r
- Thunk.Return.VBaseOffsetOffset);\r
- \r
- Mangler.mangleFunctionEncoding(MD);\r
-}\r
-\r
-void \r
-ItaniumMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,\r
- CXXDtorType Type,\r
- const ThisAdjustment &ThisAdjustment,\r
- raw_ostream &Out) {\r
- // <special-name> ::= T <call-offset> <base encoding>\r
- // # base is the nominal target function of thunk\r
- CXXNameMangler Mangler(*this, Out, DD, Type);\r
- Mangler.getStream() << "_ZT";\r
-\r
- // Mangle the 'this' pointer adjustment.\r
- Mangler.mangleCallOffset(ThisAdjustment.NonVirtual, \r
- ThisAdjustment.VCallOffsetOffset);\r
-\r
- Mangler.mangleFunctionEncoding(DD);\r
-}\r
-\r
-/// mangleGuardVariable - Returns the mangled name for a guard variable\r
-/// for the passed in VarDecl.\r
-void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D,\r
- raw_ostream &Out) {\r
- // <special-name> ::= GV <object name> # Guard variable for one-time\r
- // # initialization\r
- CXXNameMangler Mangler(*this, Out);\r
- Mangler.getStream() << "_ZGV";\r
- Mangler.mangleName(D);\r
-}\r
-\r
-void ItaniumMangleContext::mangleReferenceTemporary(const VarDecl *D,\r
- raw_ostream &Out) {\r
- // We match the GCC mangling here.\r
- // <special-name> ::= GR <object name>\r
- CXXNameMangler Mangler(*this, Out);\r
- Mangler.getStream() << "_ZGR";\r
- Mangler.mangleName(D);\r
-}\r
-\r
-void ItaniumMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,\r
- raw_ostream &Out) {\r
- // <special-name> ::= TV <type> # virtual table\r
- CXXNameMangler Mangler(*this, Out);\r
- Mangler.getStream() << "_ZTV";\r
- Mangler.mangleNameOrStandardSubstitution(RD);\r
-}\r
-\r
-void ItaniumMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,\r
- raw_ostream &Out) {\r
- // <special-name> ::= TT <type> # VTT structure\r
- CXXNameMangler Mangler(*this, Out);\r
- Mangler.getStream() << "_ZTT";\r
- Mangler.mangleNameOrStandardSubstitution(RD);\r
-}\r
-\r
-void ItaniumMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,\r
- int64_t Offset,\r
- const CXXRecordDecl *Type,\r
- raw_ostream &Out) {\r
- // <special-name> ::= TC <type> <offset number> _ <base type>\r
- CXXNameMangler Mangler(*this, Out);\r
- Mangler.getStream() << "_ZTC";\r
- Mangler.mangleNameOrStandardSubstitution(RD);\r
- Mangler.getStream() << Offset;\r
- Mangler.getStream() << '_';\r
- Mangler.mangleNameOrStandardSubstitution(Type);\r
-}\r
-\r
-void ItaniumMangleContext::mangleCXXRTTI(QualType Ty,\r
- raw_ostream &Out) {\r
- // <special-name> ::= TI <type> # typeinfo structure\r
- assert(!Ty.hasQualifiers() && "RTTI info cannot have top-level qualifiers");\r
- CXXNameMangler Mangler(*this, Out);\r
- Mangler.getStream() << "_ZTI";\r
- Mangler.mangleType(Ty);\r
-}\r
-\r
-void ItaniumMangleContext::mangleCXXRTTIName(QualType Ty,\r
- raw_ostream &Out) {\r
- // <special-name> ::= TS <type> # typeinfo name (null terminated byte string)\r
- CXXNameMangler Mangler(*this, Out);\r
- Mangler.getStream() << "_ZTS";\r
- Mangler.mangleType(Ty);\r
-}\r
-\r
-MangleContext *clang::createItaniumMangleContext(ASTContext &Context,\r
- DiagnosticsEngine &Diags) {\r
- return new ItaniumMangleContext(Context, Diags);\r
-}\r
+//===--- 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);
+}
-//===--- MicrosoftMangle.cpp - Microsoft Visual C++ Name Mangling ---------===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This provides C++ name mangling targeting the Microsoft Visual C++ ABI.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "clang/AST/Mangle.h"\r
-#include "clang/AST/ASTContext.h"\r
-#include "clang/AST/Attr.h"\r
-#include "clang/AST/CharUnits.h"\r
-#include "clang/AST/Decl.h"\r
-#include "clang/AST/DeclCXX.h"\r
-#include "clang/AST/DeclObjC.h"\r
-#include "clang/AST/DeclTemplate.h"\r
-#include "clang/AST/ExprCXX.h"\r
-#include "clang/Basic/ABI.h"\r
-#include "clang/Basic/DiagnosticOptions.h"\r
-#include <map>\r
-\r
-using namespace clang;\r
-\r
-namespace {\r
-\r
-/// MicrosoftCXXNameMangler - Manage the mangling of a single name for the\r
-/// Microsoft Visual C++ ABI.\r
-class MicrosoftCXXNameMangler {\r
- MangleContext &Context;\r
- raw_ostream &Out;\r
-\r
- // FIXME: audit the performance of BackRefMap as it might do way too many\r
- // copying of strings.\r
- typedef std::map<std::string, unsigned> BackRefMap;\r
- BackRefMap NameBackReferences;\r
- bool UseNameBackReferences;\r
-\r
- typedef llvm::DenseMap<void*, unsigned> ArgBackRefMap;\r
- ArgBackRefMap TypeBackReferences;\r
-\r
- ASTContext &getASTContext() const { return Context.getASTContext(); }\r
-\r
-public:\r
- MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)\r
- : Context(C), Out(Out_), UseNameBackReferences(true) { }\r
-\r
- raw_ostream &getStream() const { return Out; }\r
-\r
- void mangle(const NamedDecl *D, StringRef Prefix = "\01?");\r
- void mangleName(const NamedDecl *ND);\r
- void mangleFunctionEncoding(const FunctionDecl *FD);\r
- void mangleVariableEncoding(const VarDecl *VD);\r
- void mangleNumber(int64_t Number);\r
- void mangleNumber(const llvm::APSInt &Value);\r
- void mangleType(QualType T, SourceRange Range, bool MangleQualifiers = true);\r
-\r
-private:\r
- void disableBackReferences() { UseNameBackReferences = false; }\r
- void mangleUnqualifiedName(const NamedDecl *ND) {\r
- mangleUnqualifiedName(ND, ND->getDeclName());\r
- }\r
- void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name);\r
- void mangleSourceName(const IdentifierInfo *II);\r
- void manglePostfix(const DeclContext *DC, bool NoFunction=false);\r
- void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);\r
- void mangleQualifiers(Qualifiers Quals, bool IsMember);\r
- void manglePointerQualifiers(Qualifiers Quals);\r
-\r
- void mangleUnscopedTemplateName(const TemplateDecl *ND);\r
- void mangleTemplateInstantiationName(const TemplateDecl *TD,\r
- const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs);\r
- void mangleObjCMethodName(const ObjCMethodDecl *MD);\r
- void mangleLocalName(const FunctionDecl *FD);\r
-\r
- void mangleArgumentType(QualType T, SourceRange Range);\r
-\r
- // Declare manglers for every type class.\r
-#define ABSTRACT_TYPE(CLASS, PARENT)\r
-#define NON_CANONICAL_TYPE(CLASS, PARENT)\r
-#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T, \\r
- SourceRange Range);\r
-#include "clang/AST/TypeNodes.def"\r
-#undef ABSTRACT_TYPE\r
-#undef NON_CANONICAL_TYPE\r
-#undef TYPE\r
- \r
- void mangleType(const TagType*);\r
- void mangleType(const FunctionType *T, const FunctionDecl *D,\r
- bool IsStructor, bool IsInstMethod);\r
- void mangleType(const ArrayType *T, bool IsGlobal);\r
- void mangleExtraDimensions(QualType T);\r
- void mangleFunctionClass(const FunctionDecl *FD);\r
- void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false);\r
- void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean);\r
- void mangleExpression(const Expr *E);\r
- void mangleThrowSpecification(const FunctionProtoType *T);\r
-\r
- void mangleTemplateArgs(\r
- const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs);\r
-\r
-};\r
-\r
-/// MicrosoftMangleContext - Overrides the default MangleContext for the\r
-/// Microsoft Visual C++ ABI.\r
-class MicrosoftMangleContext : public MangleContext {\r
-public:\r
- MicrosoftMangleContext(ASTContext &Context,\r
- DiagnosticsEngine &Diags) : MangleContext(Context, Diags) { }\r
- virtual bool shouldMangleDeclName(const NamedDecl *D);\r
- virtual void mangleName(const NamedDecl *D, raw_ostream &Out);\r
- virtual void mangleThunk(const CXXMethodDecl *MD,\r
- const ThunkInfo &Thunk,\r
- raw_ostream &);\r
- virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,\r
- const ThisAdjustment &ThisAdjustment,\r
- raw_ostream &);\r
- virtual void mangleCXXVTable(const CXXRecordDecl *RD,\r
- raw_ostream &);\r
- virtual void mangleCXXVTT(const CXXRecordDecl *RD,\r
- raw_ostream &);\r
- virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,\r
- const CXXRecordDecl *Type,\r
- raw_ostream &);\r
- virtual void mangleCXXRTTI(QualType T, raw_ostream &);\r
- virtual void mangleCXXRTTIName(QualType T, raw_ostream &);\r
- virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,\r
- raw_ostream &);\r
- virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,\r
- raw_ostream &);\r
- virtual void mangleReferenceTemporary(const clang::VarDecl *,\r
- raw_ostream &);\r
-};\r
-\r
-}\r
-\r
-static bool isInCLinkageSpecification(const Decl *D) {\r
- D = D->getCanonicalDecl();\r
- for (const DeclContext *DC = D->getDeclContext();\r
- !DC->isTranslationUnit(); DC = DC->getParent()) {\r
- if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))\r
- return Linkage->getLanguage() == LinkageSpecDecl::lang_c;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) {\r
- // In C, functions with no attributes never need to be mangled. Fastpath them.\r
- if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())\r
- return false;\r
-\r
- // Any decl can be declared with __asm("foo") on it, and this takes precedence\r
- // over all other naming in the .o file.\r
- if (D->hasAttr<AsmLabelAttr>())\r
- return true;\r
-\r
- // Clang's "overloadable" attribute extension to C/C++ implies name mangling\r
- // (always) as does passing a C++ member function and a function\r
- // whose name is not a simple identifier.\r
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);\r
- if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) ||\r
- !FD->getDeclName().isIdentifier()))\r
- return true;\r
-\r
- // Otherwise, no mangling is done outside C++ mode.\r
- if (!getASTContext().getLangOpts().CPlusPlus)\r
- return false;\r
-\r
- // Variables at global scope with internal linkage are not mangled.\r
- if (!FD) {\r
- const DeclContext *DC = D->getDeclContext();\r
- if (DC->isTranslationUnit() && D->getLinkage() == InternalLinkage)\r
- return false;\r
- }\r
-\r
- // C functions and "main" are not mangled.\r
- if ((FD && FD->isMain()) || isInCLinkageSpecification(D))\r
- return false;\r
-\r
- return true;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,\r
- StringRef Prefix) {\r
- // MSVC doesn't mangle C++ names the same way it mangles extern "C" names.\r
- // Therefore it's really important that we don't decorate the\r
- // name with leading underscores or leading/trailing at signs. So, by\r
- // default, we emit an asm marker at the start so we get the name right.\r
- // Callers can override this with a custom prefix.\r
-\r
- // Any decl can be declared with __asm("foo") on it, and this takes precedence\r
- // over all other naming in the .o file.\r
- if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {\r
- // If we have an asm name, then we use it as the mangling.\r
- Out << '\01' << ALA->getLabel();\r
- return;\r
- }\r
-\r
- // <mangled-name> ::= ? <name> <type-encoding>\r
- Out << Prefix;\r
- mangleName(D);\r
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))\r
- mangleFunctionEncoding(FD);\r
- else if (const VarDecl *VD = dyn_cast<VarDecl>(D))\r
- mangleVariableEncoding(VD);\r
- else {\r
- // TODO: Fields? Can MSVC even mangle them?\r
- // Issue a diagnostic for now.\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this declaration yet");\r
- Diags.Report(D->getLocation(), DiagID)\r
- << D->getSourceRange();\r
- }\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {\r
- // <type-encoding> ::= <function-class> <function-type>\r
-\r
- // Don't mangle in the type if this isn't a decl we should typically mangle.\r
- if (!Context.shouldMangleDeclName(FD))\r
- return;\r
- \r
- // We should never ever see a FunctionNoProtoType at this point.\r
- // We don't even know how to mangle their types anyway :).\r
- const FunctionProtoType *FT = FD->getType()->castAs<FunctionProtoType>();\r
-\r
- bool InStructor = false, InInstMethod = false;\r
- const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);\r
- if (MD) {\r
- if (MD->isInstance())\r
- InInstMethod = true;\r
- if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))\r
- InStructor = true;\r
- }\r
-\r
- // First, the function class.\r
- mangleFunctionClass(FD);\r
-\r
- mangleType(FT, FD, InStructor, InInstMethod);\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {\r
- // <type-encoding> ::= <storage-class> <variable-type>\r
- // <storage-class> ::= 0 # private static member\r
- // ::= 1 # protected static member\r
- // ::= 2 # public static member\r
- // ::= 3 # global\r
- // ::= 4 # static local\r
- \r
- // The first character in the encoding (after the name) is the storage class.\r
- if (VD->isStaticDataMember()) {\r
- // If it's a static member, it also encodes the access level.\r
- switch (VD->getAccess()) {\r
- default:\r
- case AS_private: Out << '0'; break;\r
- case AS_protected: Out << '1'; break;\r
- case AS_public: Out << '2'; break;\r
- }\r
- }\r
- else if (!VD->isStaticLocal())\r
- Out << '3';\r
- else\r
- Out << '4';\r
- // Now mangle the type.\r
- // <variable-type> ::= <type> <cvr-qualifiers>\r
- // ::= <type> <pointee-cvr-qualifiers> # pointers, references\r
- // Pointers and references are odd. The type of 'int * const foo;' gets\r
- // mangled as 'QAHA' instead of 'PAHB', for example.\r
- TypeLoc TL = VD->getTypeSourceInfo()->getTypeLoc();\r
- QualType Ty = TL.getType();\r
- if (Ty->isPointerType() || Ty->isReferenceType()) {\r
- mangleType(Ty, TL.getSourceRange());\r
- mangleQualifiers(Ty->getPointeeType().getQualifiers(), false);\r
- } else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) {\r
- // Global arrays are funny, too.\r
- mangleType(AT, true);\r
- mangleQualifiers(Ty.getQualifiers(), false);\r
- } else {\r
- mangleType(Ty.getLocalUnqualifiedType(), TL.getSourceRange());\r
- mangleQualifiers(Ty.getLocalQualifiers(), false);\r
- }\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {\r
- // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @\r
- const DeclContext *DC = ND->getDeclContext();\r
-\r
- // Always start with the unqualified name.\r
- mangleUnqualifiedName(ND); \r
-\r
- // If this is an extern variable declared locally, the relevant DeclContext\r
- // is that of the containing namespace, or the translation unit.\r
- if (isa<FunctionDecl>(DC) && ND->hasLinkage())\r
- while (!DC->isNamespace() && !DC->isTranslationUnit())\r
- DC = DC->getParent();\r
-\r
- manglePostfix(DC);\r
-\r
- // Terminate the whole name with an '@'.\r
- Out << '@';\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) {\r
- llvm::APSInt APSNumber(/*BitWidth=*/64, /*isUnsigned=*/false);\r
- APSNumber = Number;\r
- mangleNumber(APSNumber);\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleNumber(const llvm::APSInt &Value) {\r
- // <number> ::= [?] <decimal digit> # 1 <= Number <= 10\r
- // ::= [?] <hex digit>+ @ # 0 or > 9; A = 0, B = 1, etc...\r
- // ::= [?] @ # 0 (alternate mangling, not emitted by VC)\r
- if (Value.isSigned() && Value.isNegative()) {\r
- Out << '?';\r
- mangleNumber(llvm::APSInt(Value.abs()));\r
- return;\r
- }\r
- llvm::APSInt Temp(Value);\r
- // There's a special shorter mangling for 0, but Microsoft\r
- // chose not to use it. Instead, 0 gets mangled as "A@". Oh well...\r
- if (Value.uge(1) && Value.ule(10)) {\r
- --Temp;\r
- Temp.print(Out, false);\r
- } else {\r
- // We have to build up the encoding in reverse order, so it will come\r
- // out right when we write it out.\r
- char Encoding[64];\r
- char *EndPtr = Encoding+sizeof(Encoding);\r
- char *CurPtr = EndPtr;\r
- llvm::APSInt NibbleMask(Value.getBitWidth(), Value.isUnsigned());\r
- NibbleMask = 0xf;\r
- do {\r
- *--CurPtr = 'A' + Temp.And(NibbleMask).getLimitedValue(0xf);\r
- Temp = Temp.lshr(4);\r
- } while (Temp != 0);\r
- Out.write(CurPtr, EndPtr-CurPtr);\r
- Out << '@';\r
- }\r
-}\r
-\r
-static const TemplateDecl *\r
-isTemplate(const NamedDecl *ND,\r
- SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {\r
- // Check if we have a function template.\r
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){\r
- if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {\r
- if (FD->getTemplateSpecializationArgsAsWritten()) {\r
- const ASTTemplateArgumentListInfo *ArgList =\r
- FD->getTemplateSpecializationArgsAsWritten();\r
- TemplateArgs.append(ArgList->getTemplateArgs(),\r
- ArgList->getTemplateArgs() +\r
- ArgList->NumTemplateArgs);\r
- } else {\r
- const TemplateArgumentList *ArgList =\r
- FD->getTemplateSpecializationArgs();\r
- TemplateArgumentListInfo LI;\r
- for (unsigned i = 0, e = ArgList->size(); i != e; ++i)\r
- TemplateArgs.push_back(TemplateArgumentLoc(ArgList->get(i),\r
- FD->getTypeSourceInfo()));\r
- }\r
- return TD;\r
- }\r
- }\r
-\r
- // Check if we have a class template.\r
- if (const ClassTemplateSpecializationDecl *Spec =\r
- dyn_cast<ClassTemplateSpecializationDecl>(ND)) {\r
- TypeSourceInfo *TSI = Spec->getTypeAsWritten();\r
- if (TSI) {\r
- TemplateSpecializationTypeLoc TSTL =\r
- cast<TemplateSpecializationTypeLoc>(TSI->getTypeLoc());\r
- TemplateArgumentListInfo LI(TSTL.getLAngleLoc(), TSTL.getRAngleLoc());\r
- for (unsigned i = 0, e = TSTL.getNumArgs(); i != e; ++i)\r
- TemplateArgs.push_back(TSTL.getArgLoc(i));\r
- } else {\r
- TemplateArgumentListInfo LI;\r
- const TemplateArgumentList &ArgList =\r
- Spec->getTemplateArgs();\r
- for (unsigned i = 0, e = ArgList.size(); i != e; ++i)\r
- TemplateArgs.push_back(TemplateArgumentLoc(ArgList[i],\r
- TemplateArgumentLocInfo()));\r
- }\r
- return Spec->getSpecializedTemplate();\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-void\r
-MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,\r
- DeclarationName Name) {\r
- // <unqualified-name> ::= <operator-name>\r
- // ::= <ctor-dtor-name>\r
- // ::= <source-name>\r
- // ::= <template-name>\r
- SmallVector<TemplateArgumentLoc, 2> TemplateArgs;\r
- // Check if we have a template.\r
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {\r
- // We have a template.\r
- // Here comes the tricky thing: if we need to mangle something like\r
- // void foo(A::X<Y>, B::X<Y>),\r
- // the X<Y> part is aliased. However, if you need to mangle\r
- // void foo(A::X<A::Y>, A::X<B::Y>),\r
- // the A::X<> part is not aliased.\r
- // That said, from the mangler's perspective we have a structure like this:\r
- // namespace[s] -> type[ -> template-parameters]\r
- // but from the Clang perspective we have\r
- // type [ -> template-parameters]\r
- // \-> namespace[s]\r
- // What we do is we create a new mangler, mangle the same type (without\r
- // a namespace suffix) using the extra mangler with back references\r
- // disabled (to avoid infinite recursion) and then use the mangled type\r
- // name as a key to check the mangling of different types for aliasing.\r
-\r
- std::string BackReferenceKey;\r
- BackRefMap::iterator Found;\r
- if (UseNameBackReferences) {\r
- llvm::raw_string_ostream Stream(BackReferenceKey);\r
- MicrosoftCXXNameMangler Extra(Context, Stream);\r
- Extra.disableBackReferences();\r
- Extra.mangleUnqualifiedName(ND, Name);\r
- Stream.flush();\r
-\r
- Found = NameBackReferences.find(BackReferenceKey);\r
- }\r
- if (!UseNameBackReferences || Found == NameBackReferences.end()) {\r
- mangleTemplateInstantiationName(TD, TemplateArgs);\r
- if (UseNameBackReferences && NameBackReferences.size() < 10) {\r
- size_t Size = NameBackReferences.size();\r
- NameBackReferences[BackReferenceKey] = Size;\r
- }\r
- } else {\r
- Out << Found->second;\r
- }\r
- return;\r
- }\r
-\r
- switch (Name.getNameKind()) {\r
- case DeclarationName::Identifier: {\r
- if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {\r
- mangleSourceName(II);\r
- break;\r
- }\r
- \r
- // Otherwise, an anonymous entity. We must have a declaration.\r
- assert(ND && "mangling empty name without declaration");\r
- \r
- if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {\r
- if (NS->isAnonymousNamespace()) {\r
- Out << "?A@";\r
- break;\r
- }\r
- }\r
- \r
- // We must have an anonymous struct.\r
- const TagDecl *TD = cast<TagDecl>(ND);\r
- if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) {\r
- assert(TD->getDeclContext() == D->getDeclContext() &&\r
- "Typedef should not be in another decl context!");\r
- assert(D->getDeclName().getAsIdentifierInfo() &&\r
- "Typedef was not named!");\r
- mangleSourceName(D->getDeclName().getAsIdentifierInfo());\r
- break;\r
- }\r
-\r
- // When VC encounters an anonymous type with no tag and no typedef,\r
- // it literally emits '<unnamed-tag>'.\r
- Out << "<unnamed-tag>";\r
- break;\r
- }\r
- \r
- case DeclarationName::ObjCZeroArgSelector:\r
- case DeclarationName::ObjCOneArgSelector:\r
- case DeclarationName::ObjCMultiArgSelector:\r
- llvm_unreachable("Can't mangle Objective-C selector names here!");\r
- \r
- case DeclarationName::CXXConstructorName:\r
- Out << "?0";\r
- break;\r
- \r
- case DeclarationName::CXXDestructorName:\r
- Out << "?1";\r
- break;\r
- \r
- case DeclarationName::CXXConversionFunctionName:\r
- // <operator-name> ::= ?B # (cast)\r
- // The target type is encoded as the return type.\r
- Out << "?B";\r
- break;\r
- \r
- case DeclarationName::CXXOperatorName:\r
- mangleOperatorName(Name.getCXXOverloadedOperator(), ND->getLocation());\r
- break;\r
- \r
- case DeclarationName::CXXLiteralOperatorName: {\r
- // FIXME: Was this added in VS2010? Does MS even know how to mangle this?\r
- DiagnosticsEngine Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this literal operator yet");\r
- Diags.Report(ND->getLocation(), DiagID);\r
- break;\r
- }\r
- \r
- case DeclarationName::CXXUsingDirective:\r
- llvm_unreachable("Can't mangle a using directive name!");\r
- }\r
-}\r
-\r
-void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC,\r
- bool NoFunction) {\r
- // <postfix> ::= <unqualified-name> [<postfix>]\r
- // ::= <substitution> [<postfix>]\r
-\r
- if (!DC) return;\r
-\r
- while (isa<LinkageSpecDecl>(DC))\r
- DC = DC->getParent();\r
-\r
- if (DC->isTranslationUnit())\r
- return;\r
-\r
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {\r
- Context.mangleBlock(BD, Out);\r
- Out << '@';\r
- return manglePostfix(DC->getParent(), NoFunction);\r
- }\r
-\r
- if (NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)))\r
- return;\r
- else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC))\r
- mangleObjCMethodName(Method);\r
- else if (const FunctionDecl *Func = dyn_cast<FunctionDecl>(DC))\r
- mangleLocalName(Func);\r
- else {\r
- mangleUnqualifiedName(cast<NamedDecl>(DC));\r
- manglePostfix(DC->getParent(), NoFunction);\r
- }\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,\r
- SourceLocation Loc) {\r
- switch (OO) {\r
- // ?0 # constructor\r
- // ?1 # destructor\r
- // <operator-name> ::= ?2 # new\r
- case OO_New: Out << "?2"; break;\r
- // <operator-name> ::= ?3 # delete\r
- case OO_Delete: Out << "?3"; break;\r
- // <operator-name> ::= ?4 # =\r
- case OO_Equal: Out << "?4"; break;\r
- // <operator-name> ::= ?5 # >>\r
- case OO_GreaterGreater: Out << "?5"; break;\r
- // <operator-name> ::= ?6 # <<\r
- case OO_LessLess: Out << "?6"; break;\r
- // <operator-name> ::= ?7 # !\r
- case OO_Exclaim: Out << "?7"; break;\r
- // <operator-name> ::= ?8 # ==\r
- case OO_EqualEqual: Out << "?8"; break;\r
- // <operator-name> ::= ?9 # !=\r
- case OO_ExclaimEqual: Out << "?9"; break;\r
- // <operator-name> ::= ?A # []\r
- case OO_Subscript: Out << "?A"; break;\r
- // ?B # conversion\r
- // <operator-name> ::= ?C # ->\r
- case OO_Arrow: Out << "?C"; break;\r
- // <operator-name> ::= ?D # *\r
- case OO_Star: Out << "?D"; break;\r
- // <operator-name> ::= ?E # ++\r
- case OO_PlusPlus: Out << "?E"; break;\r
- // <operator-name> ::= ?F # --\r
- case OO_MinusMinus: Out << "?F"; break;\r
- // <operator-name> ::= ?G # -\r
- case OO_Minus: Out << "?G"; break;\r
- // <operator-name> ::= ?H # +\r
- case OO_Plus: Out << "?H"; break;\r
- // <operator-name> ::= ?I # &\r
- case OO_Amp: Out << "?I"; break;\r
- // <operator-name> ::= ?J # ->*\r
- case OO_ArrowStar: Out << "?J"; break;\r
- // <operator-name> ::= ?K # /\r
- case OO_Slash: Out << "?K"; break;\r
- // <operator-name> ::= ?L # %\r
- case OO_Percent: Out << "?L"; break;\r
- // <operator-name> ::= ?M # <\r
- case OO_Less: Out << "?M"; break;\r
- // <operator-name> ::= ?N # <=\r
- case OO_LessEqual: Out << "?N"; break;\r
- // <operator-name> ::= ?O # >\r
- case OO_Greater: Out << "?O"; break;\r
- // <operator-name> ::= ?P # >=\r
- case OO_GreaterEqual: Out << "?P"; break;\r
- // <operator-name> ::= ?Q # ,\r
- case OO_Comma: Out << "?Q"; break;\r
- // <operator-name> ::= ?R # ()\r
- case OO_Call: Out << "?R"; break;\r
- // <operator-name> ::= ?S # ~\r
- case OO_Tilde: Out << "?S"; break;\r
- // <operator-name> ::= ?T # ^\r
- case OO_Caret: Out << "?T"; break;\r
- // <operator-name> ::= ?U # |\r
- case OO_Pipe: Out << "?U"; break;\r
- // <operator-name> ::= ?V # &&\r
- case OO_AmpAmp: Out << "?V"; break;\r
- // <operator-name> ::= ?W # ||\r
- case OO_PipePipe: Out << "?W"; break;\r
- // <operator-name> ::= ?X # *=\r
- case OO_StarEqual: Out << "?X"; break;\r
- // <operator-name> ::= ?Y # +=\r
- case OO_PlusEqual: Out << "?Y"; break;\r
- // <operator-name> ::= ?Z # -=\r
- case OO_MinusEqual: Out << "?Z"; break;\r
- // <operator-name> ::= ?_0 # /=\r
- case OO_SlashEqual: Out << "?_0"; break;\r
- // <operator-name> ::= ?_1 # %=\r
- case OO_PercentEqual: Out << "?_1"; break;\r
- // <operator-name> ::= ?_2 # >>=\r
- case OO_GreaterGreaterEqual: Out << "?_2"; break;\r
- // <operator-name> ::= ?_3 # <<=\r
- case OO_LessLessEqual: Out << "?_3"; break;\r
- // <operator-name> ::= ?_4 # &=\r
- case OO_AmpEqual: Out << "?_4"; break;\r
- // <operator-name> ::= ?_5 # |=\r
- case OO_PipeEqual: Out << "?_5"; break;\r
- // <operator-name> ::= ?_6 # ^=\r
- case OO_CaretEqual: Out << "?_6"; break;\r
- // ?_7 # vftable\r
- // ?_8 # vbtable\r
- // ?_9 # vcall\r
- // ?_A # typeof\r
- // ?_B # local static guard\r
- // ?_C # string\r
- // ?_D # vbase destructor\r
- // ?_E # vector deleting destructor\r
- // ?_F # default constructor closure\r
- // ?_G # scalar deleting destructor\r
- // ?_H # vector constructor iterator\r
- // ?_I # vector destructor iterator\r
- // ?_J # vector vbase constructor iterator\r
- // ?_K # virtual displacement map\r
- // ?_L # eh vector constructor iterator\r
- // ?_M # eh vector destructor iterator\r
- // ?_N # eh vector vbase constructor iterator\r
- // ?_O # copy constructor closure\r
- // ?_P<name> # udt returning <name>\r
- // ?_Q # <unknown>\r
- // ?_R0 # RTTI Type Descriptor\r
- // ?_R1 # RTTI Base Class Descriptor at (a,b,c,d)\r
- // ?_R2 # RTTI Base Class Array\r
- // ?_R3 # RTTI Class Hierarchy Descriptor\r
- // ?_R4 # RTTI Complete Object Locator\r
- // ?_S # local vftable\r
- // ?_T # local vftable constructor closure\r
- // <operator-name> ::= ?_U # new[]\r
- case OO_Array_New: Out << "?_U"; break;\r
- // <operator-name> ::= ?_V # delete[]\r
- case OO_Array_Delete: Out << "?_V"; break;\r
- \r
- case OO_Conditional: {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this conditional operator yet");\r
- Diags.Report(Loc, DiagID);\r
- break;\r
- }\r
- \r
- case OO_None:\r
- case NUM_OVERLOADED_OPERATORS:\r
- llvm_unreachable("Not an overloaded operator");\r
- }\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) {\r
- // <source name> ::= <identifier> @\r
- std::string key = II->getNameStart();\r
- BackRefMap::iterator Found;\r
- if (UseNameBackReferences)\r
- Found = NameBackReferences.find(key);\r
- if (!UseNameBackReferences || Found == NameBackReferences.end()) {\r
- Out << II->getName() << '@';\r
- if (UseNameBackReferences && NameBackReferences.size() < 10) {\r
- size_t Size = NameBackReferences.size();\r
- NameBackReferences[key] = Size;\r
- }\r
- } else {\r
- Out << Found->second;\r
- }\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {\r
- Context.mangleObjCMethodName(MD, Out);\r
-}\r
-\r
-// Find out how many function decls live above this one and return an integer\r
-// suitable for use as the number in a numbered anonymous scope.\r
-// TODO: Memoize.\r
-static unsigned getLocalNestingLevel(const FunctionDecl *FD) {\r
- const DeclContext *DC = FD->getParent();\r
- int level = 1;\r
-\r
- while (DC && !DC->isTranslationUnit()) {\r
- if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) level++;\r
- DC = DC->getParent();\r
- }\r
-\r
- return 2*level;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleLocalName(const FunctionDecl *FD) {\r
- // <nested-name> ::= <numbered-anonymous-scope> ? <mangled-name>\r
- // <numbered-anonymous-scope> ::= ? <number>\r
- // Even though the name is rendered in reverse order (e.g.\r
- // A::B::C is rendered as C@B@A), VC numbers the scopes from outermost to\r
- // innermost. So a method bar in class C local to function foo gets mangled\r
- // as something like:\r
- // ?bar@C@?1??foo@@YAXXZ@QAEXXZ\r
- // This is more apparent when you have a type nested inside a method of a\r
- // type nested inside a function. A method baz in class D local to method\r
- // bar of class C local to function foo gets mangled as:\r
- // ?baz@D@?3??bar@C@?1??foo@@YAXXZ@QAEXXZ@QAEXXZ\r
- // This scheme is general enough to support GCC-style nested\r
- // functions. You could have a method baz of class C inside a function bar\r
- // inside a function foo, like so:\r
- // ?baz@C@?3??bar@?1??foo@@YAXXZ@YAXXZ@QAEXXZ\r
- int NestLevel = getLocalNestingLevel(FD);\r
- Out << '?';\r
- mangleNumber(NestLevel);\r
- Out << '?';\r
- mangle(FD, "?");\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(\r
- const TemplateDecl *TD,\r
- const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {\r
- // <template-name> ::= <unscoped-template-name> <template-args>\r
- // ::= <substitution>\r
- // Always start with the unqualified name.\r
-\r
- // Templates have their own context for back references.\r
- ArgBackRefMap OuterArgsContext;\r
- BackRefMap OuterTemplateContext;\r
- NameBackReferences.swap(OuterTemplateContext);\r
- TypeBackReferences.swap(OuterArgsContext);\r
-\r
- mangleUnscopedTemplateName(TD);\r
- mangleTemplateArgs(TemplateArgs);\r
-\r
- // Restore the previous back reference contexts.\r
- NameBackReferences.swap(OuterTemplateContext);\r
- TypeBackReferences.swap(OuterArgsContext);\r
-}\r
-\r
-void\r
-MicrosoftCXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *TD) {\r
- // <unscoped-template-name> ::= ?$ <unqualified-name>\r
- Out << "?$";\r
- mangleUnqualifiedName(TD);\r
-}\r
-\r
-void\r
-MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value,\r
- bool IsBoolean) {\r
- // <integer-literal> ::= $0 <number>\r
- Out << "$0";\r
- // Make sure booleans are encoded as 0/1.\r
- if (IsBoolean && Value.getBoolValue())\r
- mangleNumber(1);\r
- else\r
- mangleNumber(Value);\r
-}\r
-\r
-void\r
-MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {\r
- // See if this is a constant expression.\r
- llvm::APSInt Value;\r
- if (E->isIntegerConstantExpr(Value, Context.getASTContext())) {\r
- mangleIntegerLiteral(Value, E->getType()->isBooleanType());\r
- return;\r
- }\r
-\r
- // As bad as this diagnostic is, it's better than crashing.\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot yet mangle expression type %0");\r
- Diags.Report(E->getExprLoc(), DiagID)\r
- << E->getStmtClassName() << E->getSourceRange();\r
-}\r
-\r
-void\r
-MicrosoftCXXNameMangler::mangleTemplateArgs(\r
- const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {\r
- // <template-args> ::= {<type> | <integer-literal>}+ @\r
- unsigned NumTemplateArgs = TemplateArgs.size();\r
- for (unsigned i = 0; i < NumTemplateArgs; ++i) {\r
- const TemplateArgumentLoc &TAL = TemplateArgs[i];\r
- const TemplateArgument &TA = TAL.getArgument();\r
- switch (TA.getKind()) {\r
- case TemplateArgument::Null:\r
- llvm_unreachable("Can't mangle null template arguments!");\r
- case TemplateArgument::Type:\r
- mangleType(TA.getAsType(), TAL.getSourceRange());\r
- break;\r
- case TemplateArgument::Integral:\r
- mangleIntegerLiteral(TA.getAsIntegral(),\r
- TA.getIntegralType()->isBooleanType());\r
- break;\r
- case TemplateArgument::Expression:\r
- mangleExpression(TA.getAsExpr());\r
- break;\r
- case TemplateArgument::Template:\r
- case TemplateArgument::TemplateExpansion:\r
- case TemplateArgument::Declaration:\r
- case TemplateArgument::NullPtr:\r
- case TemplateArgument::Pack: {\r
- // Issue a diagnostic.\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this %select{ERROR|ERROR|pointer/reference|nullptr|"\r
- "integral|template|template pack expansion|ERROR|parameter pack}0 "\r
- "template argument yet");\r
- Diags.Report(TAL.getLocation(), DiagID)\r
- << TA.getKind()\r
- << TAL.getSourceRange();\r
- }\r
- }\r
- }\r
- Out << '@';\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,\r
- bool IsMember) {\r
- // <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers>\r
- // 'E' means __ptr64 (32-bit only); 'F' means __unaligned (32/64-bit only);\r
- // 'I' means __restrict (32/64-bit).\r
- // Note that the MSVC __restrict keyword isn't the same as the C99 restrict\r
- // keyword!\r
- // <base-cvr-qualifiers> ::= A # near\r
- // ::= B # near const\r
- // ::= C # near volatile\r
- // ::= D # near const volatile\r
- // ::= E # far (16-bit)\r
- // ::= F # far const (16-bit)\r
- // ::= G # far volatile (16-bit)\r
- // ::= H # far const volatile (16-bit)\r
- // ::= I # huge (16-bit)\r
- // ::= J # huge const (16-bit)\r
- // ::= K # huge volatile (16-bit)\r
- // ::= L # huge const volatile (16-bit)\r
- // ::= M <basis> # based\r
- // ::= N <basis> # based const\r
- // ::= O <basis> # based volatile\r
- // ::= P <basis> # based const volatile\r
- // ::= Q # near member\r
- // ::= R # near const member\r
- // ::= S # near volatile member\r
- // ::= T # near const volatile member\r
- // ::= U # far member (16-bit)\r
- // ::= V # far const member (16-bit)\r
- // ::= W # far volatile member (16-bit)\r
- // ::= X # far const volatile member (16-bit)\r
- // ::= Y # huge member (16-bit)\r
- // ::= Z # huge const member (16-bit)\r
- // ::= 0 # huge volatile member (16-bit)\r
- // ::= 1 # huge const volatile member (16-bit)\r
- // ::= 2 <basis> # based member\r
- // ::= 3 <basis> # based const member\r
- // ::= 4 <basis> # based volatile member\r
- // ::= 5 <basis> # based const volatile member\r
- // ::= 6 # near function (pointers only)\r
- // ::= 7 # far function (pointers only)\r
- // ::= 8 # near method (pointers only)\r
- // ::= 9 # far method (pointers only)\r
- // ::= _A <basis> # based function (pointers only)\r
- // ::= _B <basis> # based function (far?) (pointers only)\r
- // ::= _C <basis> # based method (pointers only)\r
- // ::= _D <basis> # based method (far?) (pointers only)\r
- // ::= _E # block (Clang)\r
- // <basis> ::= 0 # __based(void)\r
- // ::= 1 # __based(segment)?\r
- // ::= 2 <name> # __based(name)\r
- // ::= 3 # ?\r
- // ::= 4 # ?\r
- // ::= 5 # not really based\r
- bool HasConst = Quals.hasConst(),\r
- HasVolatile = Quals.hasVolatile();\r
- if (!IsMember) {\r
- if (HasConst && HasVolatile) {\r
- Out << 'D';\r
- } else if (HasVolatile) {\r
- Out << 'C';\r
- } else if (HasConst) {\r
- Out << 'B';\r
- } else {\r
- Out << 'A';\r
- }\r
- } else {\r
- if (HasConst && HasVolatile) {\r
- Out << 'T';\r
- } else if (HasVolatile) {\r
- Out << 'S';\r
- } else if (HasConst) {\r
- Out << 'R';\r
- } else {\r
- Out << 'Q';\r
- }\r
- }\r
-\r
- // FIXME: For now, just drop all extension qualifiers on the floor.\r
-}\r
-\r
-void MicrosoftCXXNameMangler::manglePointerQualifiers(Qualifiers Quals) {\r
- // <pointer-cvr-qualifiers> ::= P # no qualifiers\r
- // ::= Q # const\r
- // ::= R # volatile\r
- // ::= S # const volatile\r
- bool HasConst = Quals.hasConst(),\r
- HasVolatile = Quals.hasVolatile();\r
- if (HasConst && HasVolatile) {\r
- Out << 'S';\r
- } else if (HasVolatile) {\r
- Out << 'R';\r
- } else if (HasConst) {\r
- Out << 'Q';\r
- } else {\r
- Out << 'P';\r
- }\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleArgumentType(QualType T,\r
- SourceRange Range) {\r
- void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr();\r
- ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);\r
-\r
- if (Found == TypeBackReferences.end()) {\r
- size_t OutSizeBefore = Out.GetNumBytesInBuffer();\r
-\r
- mangleType(T, Range, false);\r
-\r
- // See if it's worth creating a back reference.\r
- // Only types longer than 1 character are considered\r
- // and only 10 back references slots are available:\r
- bool LongerThanOneChar = (Out.GetNumBytesInBuffer() - OutSizeBefore > 1);\r
- if (LongerThanOneChar && TypeBackReferences.size() < 10) {\r
- size_t Size = TypeBackReferences.size();\r
- TypeBackReferences[TypePtr] = Size;\r
- }\r
- } else {\r
- Out << Found->second;\r
- }\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,\r
- bool MangleQualifiers) {\r
- // Only operate on the canonical type!\r
- T = getASTContext().getCanonicalType(T);\r
-\r
- Qualifiers Quals = T.getLocalQualifiers();\r
- // We have to mangle these now, while we still have enough information.\r
- if (T->isAnyPointerType() || T->isMemberPointerType() ||\r
- T->isBlockPointerType()) {\r
- manglePointerQualifiers(Quals);\r
- } else if (Quals && MangleQualifiers) {\r
- mangleQualifiers(Quals, false);\r
- }\r
-\r
- SplitQualType split = T.split();\r
- const Type *ty = split.Ty;\r
-\r
- // If we're mangling a qualified array type, push the qualifiers to\r
- // the element type.\r
- if (split.Quals && isa<ArrayType>(T)) {\r
- ty = Context.getASTContext().getAsArrayType(T);\r
- }\r
-\r
- switch (ty->getTypeClass()) {\r
-#define ABSTRACT_TYPE(CLASS, PARENT)\r
-#define NON_CANONICAL_TYPE(CLASS, PARENT) \\r
- case Type::CLASS: \\r
- llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \\r
- return;\r
-#define TYPE(CLASS, PARENT) \\r
- case Type::CLASS: \\r
- mangleType(cast<CLASS##Type>(ty), Range); \\r
- break;\r
-#include "clang/AST/TypeNodes.def"\r
-#undef ABSTRACT_TYPE\r
-#undef NON_CANONICAL_TYPE\r
-#undef TYPE\r
- }\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T,\r
- SourceRange Range) {\r
- // <type> ::= <builtin-type>\r
- // <builtin-type> ::= X # void\r
- // ::= C # signed char\r
- // ::= D # char\r
- // ::= E # unsigned char\r
- // ::= F # short\r
- // ::= G # unsigned short (or wchar_t if it's not a builtin)\r
- // ::= H # int\r
- // ::= I # unsigned int\r
- // ::= J # long\r
- // ::= K # unsigned long\r
- // L # <none>\r
- // ::= M # float\r
- // ::= N # double\r
- // ::= O # long double (__float80 is mangled differently)\r
- // ::= _J # long long, __int64\r
- // ::= _K # unsigned long long, __int64\r
- // ::= _L # __int128\r
- // ::= _M # unsigned __int128\r
- // ::= _N # bool\r
- // _O # <array in parameter>\r
- // ::= _T # __float80 (Intel)\r
- // ::= _W # wchar_t\r
- // ::= _Z # __float80 (Digital Mars)\r
- switch (T->getKind()) {\r
- case BuiltinType::Void: Out << 'X'; break;\r
- case BuiltinType::SChar: Out << 'C'; break;\r
- case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'D'; break;\r
- case BuiltinType::UChar: Out << 'E'; break;\r
- case BuiltinType::Short: Out << 'F'; break;\r
- case BuiltinType::UShort: Out << 'G'; break;\r
- case BuiltinType::Int: Out << 'H'; break;\r
- case BuiltinType::UInt: Out << 'I'; break;\r
- case BuiltinType::Long: Out << 'J'; break;\r
- case BuiltinType::ULong: Out << 'K'; break;\r
- case BuiltinType::Float: Out << 'M'; break;\r
- case BuiltinType::Double: Out << 'N'; break;\r
- // TODO: Determine size and mangle accordingly\r
- case BuiltinType::LongDouble: Out << 'O'; break;\r
- case BuiltinType::LongLong: Out << "_J"; break;\r
- case BuiltinType::ULongLong: Out << "_K"; break;\r
- case BuiltinType::Int128: Out << "_L"; break;\r
- case BuiltinType::UInt128: Out << "_M"; break;\r
- case BuiltinType::Bool: Out << "_N"; break;\r
- case BuiltinType::WChar_S:\r
- case BuiltinType::WChar_U: Out << "_W"; break;\r
-\r
-#define BUILTIN_TYPE(Id, SingletonId)\r
-#define PLACEHOLDER_TYPE(Id, SingletonId) \\r
- case BuiltinType::Id:\r
-#include "clang/AST/BuiltinTypes.def"\r
- case BuiltinType::Dependent:\r
- llvm_unreachable("placeholder types shouldn't get to name mangling");\r
-\r
- case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break;\r
- case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break;\r
- case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break;\r
-\r
- case BuiltinType::OCLImage1d: Out << "PAUocl_image1d@@"; break;\r
- case BuiltinType::OCLImage1dArray: Out << "PAUocl_image1darray@@"; break;\r
- case BuiltinType::OCLImage1dBuffer: Out << "PAUocl_image1dbuffer@@"; break;\r
- case BuiltinType::OCLImage2d: Out << "PAUocl_image2d@@"; break;\r
- case BuiltinType::OCLImage2dArray: Out << "PAUocl_image2darray@@"; break;\r
- case BuiltinType::OCLImage3d: Out << "PAUocl_image3d@@"; break;\r
- \r
- case BuiltinType::NullPtr: Out << "$$T"; break;\r
-\r
- case BuiltinType::Char16:\r
- case BuiltinType::Char32:\r
- case BuiltinType::Half: {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this built-in %0 type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << T->getName(Context.getASTContext().getPrintingPolicy())\r
- << Range;\r
- break;\r
- }\r
- }\r
-}\r
-\r
-// <type> ::= <function-type>\r
-void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T,\r
- SourceRange) {\r
- // Structors only appear in decls, so at this point we know it's not a\r
- // structor type.\r
- // FIXME: This may not be lambda-friendly.\r
- Out << "$$A6";\r
- mangleType(T, NULL, false, false);\r
-}\r
-void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,\r
- SourceRange) {\r
- llvm_unreachable("Can't mangle K&R function prototypes");\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const FunctionType *T,\r
- const FunctionDecl *D,\r
- bool IsStructor,\r
- bool IsInstMethod) {\r
- // <function-type> ::= <this-cvr-qualifiers> <calling-convention>\r
- // <return-type> <argument-list> <throw-spec>\r
- const FunctionProtoType *Proto = cast<FunctionProtoType>(T);\r
-\r
- // If this is a C++ instance method, mangle the CVR qualifiers for the\r
- // this pointer.\r
- if (IsInstMethod)\r
- mangleQualifiers(Qualifiers::fromCVRMask(Proto->getTypeQuals()), false);\r
-\r
- mangleCallingConvention(T, IsInstMethod);\r
-\r
- // <return-type> ::= <type>\r
- // ::= @ # structors (they have no declared return type)\r
- if (IsStructor)\r
- Out << '@';\r
- else {\r
- QualType Result = Proto->getResultType();\r
- const Type* RT = Result.getTypePtr();\r
- if (!RT->isAnyPointerType() && !RT->isReferenceType()) {\r
- if (Result.hasQualifiers() || !RT->isBuiltinType())\r
- Out << '?';\r
- if (!RT->isBuiltinType() && !Result.hasQualifiers()) {\r
- // Lack of qualifiers for user types is mangled as 'A'.\r
- Out << 'A';\r
- }\r
- }\r
-\r
- // FIXME: Get the source range for the result type. Or, better yet,\r
- // implement the unimplemented stuff so we don't need accurate source\r
- // location info anymore :).\r
- mangleType(Result, SourceRange());\r
- }\r
-\r
- // <argument-list> ::= X # void\r
- // ::= <type>+ @\r
- // ::= <type>* Z # varargs\r
- if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {\r
- Out << 'X';\r
- } else {\r
- if (D) {\r
- // If we got a decl, use the type-as-written to make sure arrays\r
- // get mangled right. Note that we can't rely on the TSI\r
- // existing if (for example) the parameter was synthesized.\r
- for (FunctionDecl::param_const_iterator Parm = D->param_begin(),\r
- ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) {\r
- TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo();\r
- QualType Type = TSI ? TSI->getType() : (*Parm)->getType();\r
- mangleArgumentType(Type, (*Parm)->getSourceRange());\r
- }\r
- } else {\r
- // Happens for function pointer type arguments for example.\r
- for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),\r
- ArgEnd = Proto->arg_type_end();\r
- Arg != ArgEnd; ++Arg)\r
- mangleArgumentType(*Arg, SourceRange());\r
- }\r
- // <builtin-type> ::= Z # ellipsis\r
- if (Proto->isVariadic())\r
- Out << 'Z';\r
- else\r
- Out << '@';\r
- }\r
-\r
- mangleThrowSpecification(Proto);\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {\r
- // <function-class> ::= A # private: near\r
- // ::= B # private: far\r
- // ::= C # private: static near\r
- // ::= D # private: static far\r
- // ::= E # private: virtual near\r
- // ::= F # private: virtual far\r
- // ::= G # private: thunk near\r
- // ::= H # private: thunk far\r
- // ::= I # protected: near\r
- // ::= J # protected: far\r
- // ::= K # protected: static near\r
- // ::= L # protected: static far\r
- // ::= M # protected: virtual near\r
- // ::= N # protected: virtual far\r
- // ::= O # protected: thunk near\r
- // ::= P # protected: thunk far\r
- // ::= Q # public: near\r
- // ::= R # public: far\r
- // ::= S # public: static near\r
- // ::= T # public: static far\r
- // ::= U # public: virtual near\r
- // ::= V # public: virtual far\r
- // ::= W # public: thunk near\r
- // ::= X # public: thunk far\r
- // ::= Y # global near\r
- // ::= Z # global far\r
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {\r
- switch (MD->getAccess()) {\r
- default:\r
- case AS_private:\r
- if (MD->isStatic())\r
- Out << 'C';\r
- else if (MD->isVirtual())\r
- Out << 'E';\r
- else\r
- Out << 'A';\r
- break;\r
- case AS_protected:\r
- if (MD->isStatic())\r
- Out << 'K';\r
- else if (MD->isVirtual())\r
- Out << 'M';\r
- else\r
- Out << 'I';\r
- break;\r
- case AS_public:\r
- if (MD->isStatic())\r
- Out << 'S';\r
- else if (MD->isVirtual())\r
- Out << 'U';\r
- else\r
- Out << 'Q';\r
- }\r
- } else\r
- Out << 'Y';\r
-}\r
-void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T,\r
- bool IsInstMethod) {\r
- // <calling-convention> ::= A # __cdecl\r
- // ::= B # __export __cdecl\r
- // ::= C # __pascal\r
- // ::= D # __export __pascal\r
- // ::= E # __thiscall\r
- // ::= F # __export __thiscall\r
- // ::= G # __stdcall\r
- // ::= H # __export __stdcall\r
- // ::= I # __fastcall\r
- // ::= J # __export __fastcall\r
- // The 'export' calling conventions are from a bygone era\r
- // (*cough*Win16*cough*) when functions were declared for export with\r
- // that keyword. (It didn't actually export them, it just made them so\r
- // that they could be in a DLL and somebody from another module could call\r
- // them.)\r
- CallingConv CC = T->getCallConv();\r
- if (CC == CC_Default) {\r
- if (IsInstMethod) {\r
- const FunctionProtoType *FPT =\r
- T->getCanonicalTypeUnqualified().castAs<FunctionProtoType>();\r
- bool isVariadic = FPT->isVariadic();\r
- CC = getASTContext().getDefaultCXXMethodCallConv(isVariadic);\r
- } else {\r
- CC = CC_C;\r
- }\r
- }\r
- switch (CC) {\r
- default:\r
- llvm_unreachable("Unsupported CC for mangling");\r
- case CC_Default:\r
- case CC_C: Out << 'A'; break;\r
- case CC_X86Pascal: Out << 'C'; break;\r
- case CC_X86ThisCall: Out << 'E'; break;\r
- case CC_X86StdCall: Out << 'G'; break;\r
- case CC_X86FastCall: Out << 'I'; break;\r
- }\r
-}\r
-void MicrosoftCXXNameMangler::mangleThrowSpecification(\r
- const FunctionProtoType *FT) {\r
- // <throw-spec> ::= Z # throw(...) (default)\r
- // ::= @ # throw() or __declspec/__attribute__((nothrow))\r
- // ::= <type>+\r
- // NOTE: Since the Microsoft compiler ignores throw specifications, they are\r
- // all actually mangled as 'Z'. (They're ignored because their associated\r
- // functionality isn't implemented, and probably never will be.)\r
- Out << 'Z';\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,\r
- SourceRange Range) {\r
- // Probably should be mangled as a template instantiation; need to see what\r
- // VC does first.\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this unresolved dependent type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-// <type> ::= <union-type> | <struct-type> | <class-type> | <enum-type>\r
-// <union-type> ::= T <name>\r
-// <struct-type> ::= U <name>\r
-// <class-type> ::= V <name>\r
-// <enum-type> ::= W <size> <name>\r
-void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) {\r
- mangleType(cast<TagType>(T));\r
-}\r
-void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) {\r
- mangleType(cast<TagType>(T));\r
-}\r
-void MicrosoftCXXNameMangler::mangleType(const TagType *T) {\r
- switch (T->getDecl()->getTagKind()) {\r
- case TTK_Union:\r
- Out << 'T';\r
- break;\r
- case TTK_Struct:\r
- case TTK_Interface:\r
- Out << 'U';\r
- break;\r
- case TTK_Class:\r
- Out << 'V';\r
- break;\r
- case TTK_Enum:\r
- Out << 'W';\r
- Out << getASTContext().getTypeSizeInChars(\r
- cast<EnumDecl>(T->getDecl())->getIntegerType()).getQuantity();\r
- break;\r
- }\r
- mangleName(T->getDecl());\r
-}\r
-\r
-// <type> ::= <array-type>\r
-// <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>\r
-// [Y <dimension-count> <dimension>+]\r
-// <element-type> # as global\r
-// ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+]\r
-// <element-type> # as param\r
-// It's supposed to be the other way around, but for some strange reason, it\r
-// isn't. Today this behavior is retained for the sole purpose of backwards\r
-// compatibility.\r
-void MicrosoftCXXNameMangler::mangleType(const ArrayType *T, bool IsGlobal) {\r
- // This isn't a recursive mangling, so now we have to do it all in this\r
- // one call.\r
- if (IsGlobal) {\r
- manglePointerQualifiers(T->getElementType().getQualifiers());\r
- } else {\r
- Out << 'Q';\r
- }\r
- mangleExtraDimensions(T->getElementType());\r
-}\r
-void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T,\r
- SourceRange) {\r
- mangleType(cast<ArrayType>(T), false);\r
-}\r
-void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T,\r
- SourceRange) {\r
- mangleType(cast<ArrayType>(T), false);\r
-}\r
-void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T,\r
- SourceRange) {\r
- mangleType(cast<ArrayType>(T), false);\r
-}\r
-void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T,\r
- SourceRange) {\r
- mangleType(cast<ArrayType>(T), false);\r
-}\r
-void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) {\r
- SmallVector<llvm::APInt, 3> Dimensions;\r
- for (;;) {\r
- if (const ConstantArrayType *CAT =\r
- getASTContext().getAsConstantArrayType(ElementTy)) {\r
- Dimensions.push_back(CAT->getSize());\r
- ElementTy = CAT->getElementType();\r
- } else if (ElementTy->isVariableArrayType()) {\r
- const VariableArrayType *VAT =\r
- getASTContext().getAsVariableArrayType(ElementTy);\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this variable-length array yet");\r
- Diags.Report(VAT->getSizeExpr()->getExprLoc(), DiagID)\r
- << VAT->getBracketsRange();\r
- return;\r
- } else if (ElementTy->isDependentSizedArrayType()) {\r
- // The dependent expression has to be folded into a constant (TODO).\r
- const DependentSizedArrayType *DSAT =\r
- getASTContext().getAsDependentSizedArrayType(ElementTy);\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this dependent-length array yet");\r
- Diags.Report(DSAT->getSizeExpr()->getExprLoc(), DiagID)\r
- << DSAT->getBracketsRange();\r
- return;\r
- } else if (ElementTy->isIncompleteArrayType()) continue;\r
- else break;\r
- }\r
- mangleQualifiers(ElementTy.getQualifiers(), false);\r
- // If there are any additional dimensions, mangle them now.\r
- if (Dimensions.size() > 0) {\r
- Out << 'Y';\r
- // <dimension-count> ::= <number> # number of extra dimensions\r
- mangleNumber(Dimensions.size());\r
- for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim) {\r
- mangleNumber(Dimensions[Dim].getLimitedValue());\r
- }\r
- }\r
- mangleType(ElementTy.getLocalUnqualifiedType(), SourceRange());\r
-}\r
-\r
-// <type> ::= <pointer-to-member-type>\r
-// <pointer-to-member-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>\r
-// <class name> <type>\r
-void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,\r
- SourceRange Range) {\r
- QualType PointeeType = T->getPointeeType();\r
- if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {\r
- Out << '8';\r
- mangleName(T->getClass()->castAs<RecordType>()->getDecl());\r
- mangleType(FPT, NULL, false, true);\r
- } else {\r
- mangleQualifiers(PointeeType.getQualifiers(), true);\r
- mangleName(T->getClass()->castAs<RecordType>()->getDecl());\r
- mangleType(PointeeType.getLocalUnqualifiedType(), Range);\r
- }\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this template type parameter type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(\r
- const SubstTemplateTypeParmPackType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this substituted parameter pack yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-// <type> ::= <pointer-type>\r
-// <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type>\r
-void MicrosoftCXXNameMangler::mangleType(const PointerType *T,\r
- SourceRange Range) {\r
- QualType PointeeTy = T->getPointeeType();\r
- if (PointeeTy->isArrayType()) {\r
- // Pointers to arrays are mangled like arrays.\r
- mangleExtraDimensions(PointeeTy);\r
- } else if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {\r
- // Function pointers are special.\r
- Out << '6';\r
- mangleType(FT, NULL, false, false);\r
- } else {\r
- mangleQualifiers(PointeeTy.getQualifiers(), false);\r
- mangleType(PointeeTy, Range, false);\r
- }\r
-}\r
-void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,\r
- SourceRange Range) {\r
- // Object pointers never have qualifiers.\r
- Out << 'A';\r
- mangleType(T->getPointeeType(), Range);\r
-}\r
-\r
-// <type> ::= <reference-type>\r
-// <reference-type> ::= A <cvr-qualifiers> <type>\r
-void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,\r
- SourceRange Range) {\r
- Out << 'A';\r
- QualType PointeeTy = T->getPointeeType();\r
- if (!PointeeTy.hasQualifiers())\r
- // Lack of qualifiers is mangled as 'A'.\r
- Out << 'A';\r
- mangleType(PointeeTy, Range);\r
-}\r
-\r
-// <type> ::= <r-value-reference-type>\r
-// <r-value-reference-type> ::= $$Q <cvr-qualifiers> <type>\r
-void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T,\r
- SourceRange Range) {\r
- Out << "$$Q";\r
- QualType PointeeTy = T->getPointeeType();\r
- if (!PointeeTy.hasQualifiers())\r
- // Lack of qualifiers is mangled as 'A'.\r
- Out << 'A';\r
- mangleType(PointeeTy, Range);\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const ComplexType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this complex number type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const VectorType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this vector type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this extended vector type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this dependent-sized extended vector type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T,\r
- SourceRange) {\r
- // ObjC interfaces have structs underlying them.\r
- Out << 'U';\r
- mangleName(T->getDecl());\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,\r
- SourceRange Range) {\r
- // We don't allow overloading by different protocol qualification,\r
- // so mangling them isn't necessary.\r
- mangleType(T->getBaseType(), Range);\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,\r
- SourceRange Range) {\r
- Out << "_E";\r
-\r
- QualType pointee = T->getPointeeType();\r
- mangleType(pointee->castAs<FunctionProtoType>(), NULL, false, false);\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this injected class name type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this template specialization type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this dependent name type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(\r
- const DependentTemplateSpecializationType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this dependent template specialization type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this pack expansion yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this typeof(type) yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this typeof(expression) yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this decltype() yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this unary transform type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this 'auto' type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftCXXNameMangler::mangleType(const AtomicType *T,\r
- SourceRange Range) {\r
- DiagnosticsEngine &Diags = Context.getDiags();\r
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this C11 atomic type yet");\r
- Diags.Report(Range.getBegin(), DiagID)\r
- << Range;\r
-}\r
-\r
-void MicrosoftMangleContext::mangleName(const NamedDecl *D,\r
- raw_ostream &Out) {\r
- assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&\r
- "Invalid mangleName() call, argument is not a variable or function!");\r
- assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&\r
- "Invalid mangleName() call on 'structor decl!");\r
-\r
- PrettyStackTraceDecl CrashInfo(D, SourceLocation(),\r
- getASTContext().getSourceManager(),\r
- "Mangling declaration");\r
-\r
- MicrosoftCXXNameMangler Mangler(*this, Out);\r
- return Mangler.mangle(D);\r
-}\r
-void MicrosoftMangleContext::mangleThunk(const CXXMethodDecl *MD,\r
- const ThunkInfo &Thunk,\r
- raw_ostream &) {\r
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle thunk for this method yet");\r
- getDiags().Report(MD->getLocation(), DiagID);\r
-}\r
-void MicrosoftMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,\r
- CXXDtorType Type,\r
- const ThisAdjustment &,\r
- raw_ostream &) {\r
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle thunk for this destructor yet");\r
- getDiags().Report(DD->getLocation(), DiagID);\r
-}\r
-void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,\r
- raw_ostream &Out) {\r
- // <mangled-name> ::= ? <operator-name> <class-name> <storage-class>\r
- // <cvr-qualifiers> [<name>] @\r
- // <operator-name> ::= _7 # vftable\r
- // ::= _8 # vbtable\r
- // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>\r
- // is always '6' for vftables and '7' for vbtables. (The difference is\r
- // beyond me.)\r
- // TODO: vbtables.\r
- MicrosoftCXXNameMangler Mangler(*this, Out);\r
- Mangler.getStream() << "\01??_7";\r
- Mangler.mangleName(RD);\r
- Mangler.getStream() << "6B";\r
- // TODO: If the class has more than one vtable, mangle in the class it came\r
- // from.\r
- Mangler.getStream() << '@';\r
-}\r
-void MicrosoftMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,\r
- raw_ostream &) {\r
- llvm_unreachable("The MS C++ ABI does not have virtual table tables!");\r
-}\r
-void MicrosoftMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,\r
- int64_t Offset,\r
- const CXXRecordDecl *Type,\r
- raw_ostream &) {\r
- llvm_unreachable("The MS C++ ABI does not have constructor vtables!");\r
-}\r
-void MicrosoftMangleContext::mangleCXXRTTI(QualType T,\r
- raw_ostream &) {\r
- // FIXME: Give a location...\r
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle RTTI descriptors for type %0 yet");\r
- getDiags().Report(DiagID)\r
- << T.getBaseTypeIdentifier();\r
-}\r
-void MicrosoftMangleContext::mangleCXXRTTIName(QualType T,\r
- raw_ostream &) {\r
- // FIXME: Give a location...\r
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle the name of type %0 into RTTI descriptors yet");\r
- getDiags().Report(DiagID)\r
- << T.getBaseTypeIdentifier();\r
-}\r
-void MicrosoftMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,\r
- CXXCtorType Type,\r
- raw_ostream & Out) {\r
- MicrosoftCXXNameMangler mangler(*this, Out);\r
- mangler.mangle(D);\r
-}\r
-void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,\r
- CXXDtorType Type,\r
- raw_ostream & Out) {\r
- MicrosoftCXXNameMangler mangler(*this, Out);\r
- mangler.mangle(D);\r
-}\r
-void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *VD,\r
- raw_ostream &) {\r
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,\r
- "cannot mangle this reference temporary yet");\r
- getDiags().Report(VD->getLocation(), DiagID);\r
-}\r
-\r
-MangleContext *clang::createMicrosoftMangleContext(ASTContext &Context,\r
- DiagnosticsEngine &Diags) {\r
- return new MicrosoftMangleContext(Context, Diags);\r
-}\r
+//===--- 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@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@C@?1??foo@@YAXXZ@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@D@?3??bar@C@?1??foo@@YAXXZ@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@C@?3??bar@?1??foo@@YAXXZ@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);
+}
-//===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "clang/AST/NSAPI.h"\r
-#include "clang/AST/ASTContext.h"\r
-#include "clang/AST/Expr.h"\r
-\r
-using namespace clang;\r
-\r
-NSAPI::NSAPI(ASTContext &ctx)\r
- : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0),\r
- NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) {\r
-}\r
-\r
-IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {\r
- static const char *ClassName[NumClassIds] = {\r
- "NSObject",\r
- "NSString",\r
- "NSArray",\r
- "NSMutableArray",\r
- "NSDictionary",\r
- "NSMutableDictionary",\r
- "NSNumber"\r
- };\r
-\r
- if (!ClassIds[K])\r
- return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));\r
-\r
- return ClassIds[K];\r
-}\r
-\r
-Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {\r
- if (NSStringSelectors[MK].isNull()) {\r
- Selector Sel;\r
- switch (MK) {\r
- case NSStr_stringWithString:\r
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));\r
- break;\r
- case NSStr_stringWithUTF8String:\r
- Sel = Ctx.Selectors.getUnarySelector(\r
- &Ctx.Idents.get("stringWithUTF8String"));\r
- break;\r
- case NSStr_stringWithCStringEncoding: {\r
- IdentifierInfo *KeyIdents[] = {\r
- &Ctx.Idents.get("stringWithCString"),\r
- &Ctx.Idents.get("encoding")\r
- };\r
- Sel = Ctx.Selectors.getSelector(2, KeyIdents);\r
- break;\r
- }\r
- case NSStr_stringWithCString:\r
- Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));\r
- break;\r
- case NSStr_initWithString:\r
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));\r
- break;\r
- }\r
- return (NSStringSelectors[MK] = Sel);\r
- }\r
-\r
- return NSStringSelectors[MK];\r
-}\r
-\r
-llvm::Optional<NSAPI::NSStringMethodKind>\r
-NSAPI::getNSStringMethodKind(Selector Sel) const {\r
- for (unsigned i = 0; i != NumNSStringMethods; ++i) {\r
- NSStringMethodKind MK = NSStringMethodKind(i);\r
- if (Sel == getNSStringSelector(MK))\r
- return MK;\r
- }\r
-\r
- return llvm::Optional<NSStringMethodKind>();\r
-}\r
-\r
-Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {\r
- if (NSArraySelectors[MK].isNull()) {\r
- Selector Sel;\r
- switch (MK) {\r
- case NSArr_array:\r
- Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));\r
- break;\r
- case NSArr_arrayWithArray:\r
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));\r
- break;\r
- case NSArr_arrayWithObject:\r
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));\r
- break;\r
- case NSArr_arrayWithObjects:\r
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));\r
- break;\r
- case NSArr_arrayWithObjectsCount: {\r
- IdentifierInfo *KeyIdents[] = {\r
- &Ctx.Idents.get("arrayWithObjects"),\r
- &Ctx.Idents.get("count")\r
- };\r
- Sel = Ctx.Selectors.getSelector(2, KeyIdents);\r
- break;\r
- }\r
- case NSArr_initWithArray:\r
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));\r
- break;\r
- case NSArr_initWithObjects:\r
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));\r
- break;\r
- case NSArr_objectAtIndex:\r
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));\r
- break;\r
- case NSMutableArr_replaceObjectAtIndex: {\r
- IdentifierInfo *KeyIdents[] = {\r
- &Ctx.Idents.get("replaceObjectAtIndex"),\r
- &Ctx.Idents.get("withObject")\r
- };\r
- Sel = Ctx.Selectors.getSelector(2, KeyIdents);\r
- break;\r
- }\r
- }\r
- return (NSArraySelectors[MK] = Sel);\r
- }\r
-\r
- return NSArraySelectors[MK];\r
-}\r
-\r
-llvm::Optional<NSAPI::NSArrayMethodKind>\r
-NSAPI::getNSArrayMethodKind(Selector Sel) {\r
- for (unsigned i = 0; i != NumNSArrayMethods; ++i) {\r
- NSArrayMethodKind MK = NSArrayMethodKind(i);\r
- if (Sel == getNSArraySelector(MK))\r
- return MK;\r
- }\r
-\r
- return llvm::Optional<NSArrayMethodKind>();\r
-}\r
-\r
-Selector NSAPI::getNSDictionarySelector(\r
- NSDictionaryMethodKind MK) const {\r
- if (NSDictionarySelectors[MK].isNull()) {\r
- Selector Sel;\r
- switch (MK) {\r
- case NSDict_dictionary:\r
- Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));\r
- break;\r
- case NSDict_dictionaryWithDictionary:\r
- Sel = Ctx.Selectors.getUnarySelector(\r
- &Ctx.Idents.get("dictionaryWithDictionary"));\r
- break;\r
- case NSDict_dictionaryWithObjectForKey: {\r
- IdentifierInfo *KeyIdents[] = {\r
- &Ctx.Idents.get("dictionaryWithObject"),\r
- &Ctx.Idents.get("forKey")\r
- };\r
- Sel = Ctx.Selectors.getSelector(2, KeyIdents);\r
- break;\r
- }\r
- case NSDict_dictionaryWithObjectsForKeys: {\r
- IdentifierInfo *KeyIdents[] = {\r
- &Ctx.Idents.get("dictionaryWithObjects"),\r
- &Ctx.Idents.get("forKeys")\r
- };\r
- Sel = Ctx.Selectors.getSelector(2, KeyIdents);\r
- break;\r
- }\r
- case NSDict_dictionaryWithObjectsForKeysCount: {\r
- IdentifierInfo *KeyIdents[] = {\r
- &Ctx.Idents.get("dictionaryWithObjects"),\r
- &Ctx.Idents.get("forKeys"),\r
- &Ctx.Idents.get("count")\r
- };\r
- Sel = Ctx.Selectors.getSelector(3, KeyIdents);\r
- break;\r
- }\r
- case NSDict_dictionaryWithObjectsAndKeys:\r
- Sel = Ctx.Selectors.getUnarySelector(\r
- &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));\r
- break;\r
- case NSDict_initWithDictionary:\r
- Sel = Ctx.Selectors.getUnarySelector(\r
- &Ctx.Idents.get("initWithDictionary"));\r
- break;\r
- case NSDict_initWithObjectsAndKeys:\r
- Sel = Ctx.Selectors.getUnarySelector(\r
- &Ctx.Idents.get("initWithObjectsAndKeys"));\r
- break;\r
- case NSDict_objectForKey:\r
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));\r
- break;\r
- case NSMutableDict_setObjectForKey: {\r
- IdentifierInfo *KeyIdents[] = {\r
- &Ctx.Idents.get("setObject"),\r
- &Ctx.Idents.get("forKey")\r
- };\r
- Sel = Ctx.Selectors.getSelector(2, KeyIdents);\r
- break;\r
- }\r
- }\r
- return (NSDictionarySelectors[MK] = Sel);\r
- }\r
-\r
- return NSDictionarySelectors[MK];\r
-}\r
-\r
-llvm::Optional<NSAPI::NSDictionaryMethodKind>\r
-NSAPI::getNSDictionaryMethodKind(Selector Sel) {\r
- for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {\r
- NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);\r
- if (Sel == getNSDictionarySelector(MK))\r
- return MK;\r
- }\r
-\r
- return llvm::Optional<NSDictionaryMethodKind>();\r
-}\r
-\r
-Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,\r
- bool Instance) const {\r
- static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {\r
- "numberWithChar",\r
- "numberWithUnsignedChar",\r
- "numberWithShort",\r
- "numberWithUnsignedShort",\r
- "numberWithInt",\r
- "numberWithUnsignedInt",\r
- "numberWithLong",\r
- "numberWithUnsignedLong",\r
- "numberWithLongLong",\r
- "numberWithUnsignedLongLong",\r
- "numberWithFloat",\r
- "numberWithDouble",\r
- "numberWithBool",\r
- "numberWithInteger",\r
- "numberWithUnsignedInteger"\r
- };\r
- static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {\r
- "initWithChar",\r
- "initWithUnsignedChar",\r
- "initWithShort",\r
- "initWithUnsignedShort",\r
- "initWithInt",\r
- "initWithUnsignedInt",\r
- "initWithLong",\r
- "initWithUnsignedLong",\r
- "initWithLongLong",\r
- "initWithUnsignedLongLong",\r
- "initWithFloat",\r
- "initWithDouble",\r
- "initWithBool",\r
- "initWithInteger",\r
- "initWithUnsignedInteger"\r
- };\r
-\r
- Selector *Sels;\r
- const char **Names;\r
- if (Instance) {\r
- Sels = NSNumberInstanceSelectors;\r
- Names = InstanceSelectorName;\r
- } else {\r
- Sels = NSNumberClassSelectors;\r
- Names = ClassSelectorName;\r
- }\r
-\r
- if (Sels[MK].isNull())\r
- Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));\r
- return Sels[MK];\r
-}\r
-\r
-llvm::Optional<NSAPI::NSNumberLiteralMethodKind>\r
-NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {\r
- for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {\r
- NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);\r
- if (isNSNumberLiteralSelector(MK, Sel))\r
- return MK;\r
- }\r
-\r
- return llvm::Optional<NSNumberLiteralMethodKind>();\r
-}\r
-\r
-llvm::Optional<NSAPI::NSNumberLiteralMethodKind>\r
-NSAPI::getNSNumberFactoryMethodKind(QualType T) const {\r
- const BuiltinType *BT = T->getAs<BuiltinType>();\r
- if (!BT)\r
- return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();\r
-\r
- const TypedefType *TDT = T->getAs<TypedefType>();\r
- if (TDT) {\r
- QualType TDTTy = QualType(TDT, 0);\r
- if (isObjCBOOLType(TDTTy))\r
- return NSAPI::NSNumberWithBool;\r
- if (isObjCNSIntegerType(TDTTy))\r
- return NSAPI::NSNumberWithInteger;\r
- if (isObjCNSUIntegerType(TDTTy))\r
- return NSAPI::NSNumberWithUnsignedInteger;\r
- }\r
-\r
- switch (BT->getKind()) {\r
- case BuiltinType::Char_S:\r
- case BuiltinType::SChar:\r
- return NSAPI::NSNumberWithChar;\r
- case BuiltinType::Char_U:\r
- case BuiltinType::UChar:\r
- return NSAPI::NSNumberWithUnsignedChar;\r
- case BuiltinType::Short:\r
- return NSAPI::NSNumberWithShort;\r
- case BuiltinType::UShort:\r
- return NSAPI::NSNumberWithUnsignedShort;\r
- case BuiltinType::Int:\r
- return NSAPI::NSNumberWithInt;\r
- case BuiltinType::UInt:\r
- return NSAPI::NSNumberWithUnsignedInt;\r
- case BuiltinType::Long:\r
- return NSAPI::NSNumberWithLong;\r
- case BuiltinType::ULong:\r
- return NSAPI::NSNumberWithUnsignedLong;\r
- case BuiltinType::LongLong:\r
- return NSAPI::NSNumberWithLongLong;\r
- case BuiltinType::ULongLong:\r
- return NSAPI::NSNumberWithUnsignedLongLong;\r
- case BuiltinType::Float:\r
- return NSAPI::NSNumberWithFloat;\r
- case BuiltinType::Double:\r
- return NSAPI::NSNumberWithDouble;\r
- case BuiltinType::Bool:\r
- return NSAPI::NSNumberWithBool;\r
- \r
- case BuiltinType::Void:\r
- case BuiltinType::WChar_U:\r
- case BuiltinType::WChar_S:\r
- case BuiltinType::Char16:\r
- case BuiltinType::Char32:\r
- case BuiltinType::Int128:\r
- case BuiltinType::LongDouble:\r
- case BuiltinType::UInt128:\r
- case BuiltinType::NullPtr:\r
- case BuiltinType::ObjCClass:\r
- case BuiltinType::ObjCId:\r
- case BuiltinType::ObjCSel:\r
- case BuiltinType::OCLImage1d:\r
- case BuiltinType::OCLImage1dArray:\r
- case BuiltinType::OCLImage1dBuffer:\r
- case BuiltinType::OCLImage2d:\r
- case BuiltinType::OCLImage2dArray:\r
- case BuiltinType::OCLImage3d:\r
- case BuiltinType::BoundMember:\r
- case BuiltinType::Dependent:\r
- case BuiltinType::Overload:\r
- case BuiltinType::UnknownAny:\r
- case BuiltinType::ARCUnbridgedCast:\r
- case BuiltinType::Half:\r
- case BuiltinType::PseudoObject:\r
- case BuiltinType::BuiltinFn:\r
- break;\r
- }\r
- \r
- return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();\r
-}\r
-\r
-/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.\r
-bool NSAPI::isObjCBOOLType(QualType T) const {\r
- return isObjCTypedef(T, "BOOL", BOOLId);\r
-}\r
-/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.\r
-bool NSAPI::isObjCNSIntegerType(QualType T) const {\r
- return isObjCTypedef(T, "NSInteger", NSIntegerId);\r
-}\r
-/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.\r
-bool NSAPI::isObjCNSUIntegerType(QualType T) const {\r
- return isObjCTypedef(T, "NSUInteger", NSUIntegerId);\r
-}\r
-\r
-bool NSAPI::isObjCTypedef(QualType T,\r
- StringRef name, IdentifierInfo *&II) const {\r
- if (!Ctx.getLangOpts().ObjC1)\r
- return false;\r
- if (T.isNull())\r
- return false;\r
-\r
- if (!II)\r
- II = &Ctx.Idents.get(name);\r
-\r
- while (const TypedefType *TDT = T->getAs<TypedefType>()) {\r
- if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)\r
- return true;\r
- T = TDT->desugar();\r
- }\r
-\r
- return false;\r
-}\r
-\r
-bool NSAPI::isObjCEnumerator(const Expr *E,\r
- StringRef name, IdentifierInfo *&II) const {\r
- if (!Ctx.getLangOpts().ObjC1)\r
- return false;\r
- if (!E)\r
- return false;\r
-\r
- if (!II)\r
- II = &Ctx.Idents.get(name);\r
-\r
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))\r
- if (const EnumConstantDecl *\r
- EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))\r
- return EnumD->getIdentifier() == II;\r
-\r
- return false;\r
-}\r
-\r
-Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,\r
- Selector &Sel) const {\r
- if (Sel.isNull()) {\r
- SmallVector<IdentifierInfo *, 4> Idents;\r
- for (ArrayRef<StringRef>::const_iterator\r
- I = Ids.begin(), E = Ids.end(); I != E; ++I)\r
- Idents.push_back(&Ctx.Idents.get(*I));\r
- Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());\r
- }\r
- return Sel;\r
-}\r
+//===--- 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;
+}
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.");
-//===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- C++ -*-===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This file defines the TypeLoc subclasses implementations.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "clang/AST/TypeLoc.h"\r
-#include "clang/AST/ASTContext.h"\r
-#include "clang/AST/Expr.h"\r
-#include "clang/AST/TypeLocVisitor.h"\r
-#include "llvm/Support/ErrorHandling.h"\r
-#include "llvm/Support/raw_ostream.h"\r
-using namespace clang;\r
-\r
-//===----------------------------------------------------------------------===//\r
-// TypeLoc Implementation\r
-//===----------------------------------------------------------------------===//\r
-\r
-namespace {\r
- class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {\r
- public:\r
-#define ABSTRACT_TYPELOC(CLASS, PARENT)\r
-#define TYPELOC(CLASS, PARENT) \\r
- SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \\r
- return TyLoc.getLocalSourceRange(); \\r
- }\r
-#include "clang/AST/TypeLocNodes.def"\r
- };\r
-}\r
-\r
-SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {\r
- if (TL.isNull()) return SourceRange();\r
- return TypeLocRanger().Visit(TL);\r
-}\r
-\r
-namespace {\r
- class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {\r
- public:\r
-#define ABSTRACT_TYPELOC(CLASS, PARENT)\r
-#define TYPELOC(CLASS, PARENT) \\r
- unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \\r
- return TyLoc.getFullDataSize(); \\r
- }\r
-#include "clang/AST/TypeLocNodes.def"\r
- };\r
-}\r
-\r
-/// \brief Returns the size of the type source info data block.\r
-unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {\r
- if (Ty.isNull()) return 0;\r
- return TypeSizer().Visit(TypeLoc(Ty, 0));\r
-}\r
-\r
-namespace {\r
- class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {\r
- public:\r
-#define ABSTRACT_TYPELOC(CLASS, PARENT)\r
-#define TYPELOC(CLASS, PARENT) \\r
- TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \\r
- return TyLoc.getNextTypeLoc(); \\r
- }\r
-#include "clang/AST/TypeLocNodes.def"\r
- };\r
-}\r
-\r
-/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the\r
-/// TypeLoc is a PointerLoc and next TypeLoc is for "int".\r
-TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {\r
- return NextLoc().Visit(TL);\r
-}\r
-\r
-/// \brief Initializes a type location, and all of its children\r
-/// recursively, as if the entire tree had been written in the\r
-/// given location.\r
-void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, \r
- SourceLocation Loc) {\r
- while (true) {\r
- switch (TL.getTypeLocClass()) {\r
-#define ABSTRACT_TYPELOC(CLASS, PARENT)\r
-#define TYPELOC(CLASS, PARENT) \\r
- case CLASS: { \\r
- CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \\r
- TLCasted.initializeLocal(Context, Loc); \\r
- TL = TLCasted.getNextTypeLoc(); \\r
- if (!TL) return; \\r
- continue; \\r
- }\r
-#include "clang/AST/TypeLocNodes.def"\r
- }\r
- }\r
-}\r
-\r
-SourceLocation TypeLoc::getBeginLoc() const {\r
- TypeLoc Cur = *this;\r
- TypeLoc LeftMost = Cur;\r
- while (true) {\r
- switch (Cur.getTypeLocClass()) {\r
- case Elaborated:\r
- LeftMost = Cur;\r
- break;\r
- case FunctionProto:\r
- if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn()) {\r
- LeftMost = Cur;\r
- break;\r
- }\r
- /* Fall through */\r
- case FunctionNoProto:\r
- case ConstantArray:\r
- case DependentSizedArray:\r
- case IncompleteArray:\r
- case VariableArray:\r
- // FIXME: Currently QualifiedTypeLoc does not have a source range\r
- case Qualified:\r
- Cur = Cur.getNextTypeLoc();\r
- continue;\r
- default:\r
- if (!Cur.getLocalSourceRange().getBegin().isInvalid())\r
- LeftMost = Cur;\r
- Cur = Cur.getNextTypeLoc();\r
- if (Cur.isNull())\r
- break;\r
- continue;\r
- } // switch\r
- break;\r
- } // while\r
- return LeftMost.getLocalSourceRange().getBegin();\r
-}\r
-\r
-SourceLocation TypeLoc::getEndLoc() const {\r
- TypeLoc Cur = *this;\r
- TypeLoc Last;\r
- while (true) {\r
- switch (Cur.getTypeLocClass()) {\r
- default:\r
- if (!Last)\r
- Last = Cur;\r
- return Last.getLocalSourceRange().getEnd();\r
- case Paren:\r
- case ConstantArray:\r
- case DependentSizedArray:\r
- case IncompleteArray:\r
- case VariableArray:\r
- case FunctionNoProto:\r
- Last = Cur;\r
- break;\r
- case FunctionProto:\r
- if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn())\r
- Last = TypeLoc();\r
- else\r
- Last = Cur;\r
- break;\r
- case Pointer:\r
- case BlockPointer:\r
- case MemberPointer:\r
- case LValueReference:\r
- case RValueReference:\r
- case PackExpansion:\r
- if (!Last)\r
- Last = Cur;\r
- break;\r
- case Qualified:\r
- case Elaborated:\r
- break;\r
- }\r
- Cur = Cur.getNextTypeLoc();\r
- }\r
-}\r
-\r
-\r
-namespace {\r
- struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {\r
- // Overload resolution does the real work for us.\r
- static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }\r
- static bool isTypeSpec(TypeLoc _) { return false; }\r
-\r
-#define ABSTRACT_TYPELOC(CLASS, PARENT)\r
-#define TYPELOC(CLASS, PARENT) \\r
- bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \\r
- return isTypeSpec(TyLoc); \\r
- }\r
-#include "clang/AST/TypeLocNodes.def"\r
- };\r
-}\r
-\r
-\r
-/// \brief Determines if the given type loc corresponds to a\r
-/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in\r
-/// the type hierarchy, this is made somewhat complicated.\r
-///\r
-/// There are a lot of types that currently use TypeSpecTypeLoc\r
-/// because it's a convenient base class. Ideally we would not accept\r
-/// those here, but ideally we would have better implementations for\r
-/// them.\r
-bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {\r
- if (TL->getType().hasLocalQualifiers()) return false;\r
- return TSTChecker().Visit(*TL);\r
-}\r
-\r
-// Reimplemented to account for GNU/C++ extension\r
-// typeof unary-expression\r
-// where there are no parentheses.\r
-SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {\r
- if (getRParenLoc().isValid())\r
- return SourceRange(getTypeofLoc(), getRParenLoc());\r
- else\r
- return SourceRange(getTypeofLoc(),\r
- getUnderlyingExpr()->getSourceRange().getEnd());\r
-}\r
-\r
-\r
-TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {\r
- if (needsExtraLocalData())\r
- return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);\r
- switch (getTypePtr()->getKind()) {\r
- case BuiltinType::Void:\r
- return TST_void;\r
- case BuiltinType::Bool:\r
- return TST_bool;\r
- case BuiltinType::Char_U:\r
- case BuiltinType::Char_S:\r
- return TST_char;\r
- case BuiltinType::Char16:\r
- return TST_char16;\r
- case BuiltinType::Char32:\r
- return TST_char32;\r
- case BuiltinType::WChar_S:\r
- case BuiltinType::WChar_U:\r
- return TST_wchar;\r
- case BuiltinType::UChar:\r
- case BuiltinType::UShort:\r
- case BuiltinType::UInt:\r
- case BuiltinType::ULong:\r
- case BuiltinType::ULongLong:\r
- case BuiltinType::UInt128:\r
- case BuiltinType::SChar:\r
- case BuiltinType::Short:\r
- case BuiltinType::Int:\r
- case BuiltinType::Long:\r
- case BuiltinType::LongLong:\r
- case BuiltinType::Int128:\r
- case BuiltinType::Half:\r
- case BuiltinType::Float:\r
- case BuiltinType::Double:\r
- case BuiltinType::LongDouble:\r
- llvm_unreachable("Builtin type needs extra local data!");\r
- // Fall through, if the impossible happens.\r
- \r
- case BuiltinType::NullPtr:\r
- case BuiltinType::Overload:\r
- case BuiltinType::Dependent:\r
- case BuiltinType::BoundMember:\r
- case BuiltinType::UnknownAny:\r
- case BuiltinType::ARCUnbridgedCast:\r
- case BuiltinType::PseudoObject:\r
- case BuiltinType::ObjCId:\r
- case BuiltinType::ObjCClass:\r
- case BuiltinType::ObjCSel:\r
- case BuiltinType::OCLImage1d:\r
- case BuiltinType::OCLImage1dArray:\r
- case BuiltinType::OCLImage1dBuffer:\r
- case BuiltinType::OCLImage2d:\r
- case BuiltinType::OCLImage2dArray:\r
- case BuiltinType::OCLImage3d:\r
- case BuiltinType::BuiltinFn:\r
- return TST_unspecified;\r
- }\r
-\r
- llvm_unreachable("Invalid BuiltinType Kind!");\r
-}\r
-\r
-TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {\r
- while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))\r
- TL = PTL->getInnerLoc();\r
- return TL;\r
-}\r
-\r
-void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, \r
- SourceLocation Loc) {\r
- setElaboratedKeywordLoc(Loc);\r
- NestedNameSpecifierLocBuilder Builder;\r
- Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);\r
- setQualifierLoc(Builder.getWithLocInContext(Context));\r
-}\r
-\r
-void DependentNameTypeLoc::initializeLocal(ASTContext &Context, \r
- SourceLocation Loc) {\r
- setElaboratedKeywordLoc(Loc);\r
- NestedNameSpecifierLocBuilder Builder;\r
- Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);\r
- setQualifierLoc(Builder.getWithLocInContext(Context));\r
- setNameLoc(Loc);\r
-}\r
-\r
-void\r
-DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,\r
- SourceLocation Loc) {\r
- setElaboratedKeywordLoc(Loc);\r
- if (getTypePtr()->getQualifier()) {\r
- NestedNameSpecifierLocBuilder Builder;\r
- Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);\r
- setQualifierLoc(Builder.getWithLocInContext(Context));\r
- } else {\r
- setQualifierLoc(NestedNameSpecifierLoc());\r
- }\r
- setTemplateKeywordLoc(Loc);\r
- setTemplateNameLoc(Loc);\r
- setLAngleLoc(Loc);\r
- setRAngleLoc(Loc);\r
- TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),\r
- getTypePtr()->getArgs(),\r
- getArgInfos(), Loc);\r
-}\r
-\r
-void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, \r
- unsigned NumArgs,\r
- const TemplateArgument *Args,\r
- TemplateArgumentLocInfo *ArgInfos,\r
- SourceLocation Loc) {\r
- for (unsigned i = 0, e = NumArgs; i != e; ++i) {\r
- switch (Args[i].getKind()) {\r
- case TemplateArgument::Null: \r
- case TemplateArgument::Declaration:\r
- case TemplateArgument::Integral:\r
- case TemplateArgument::NullPtr:\r
- llvm_unreachable("Impossible TemplateArgument");\r
-\r
- case TemplateArgument::Expression:\r
- ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());\r
- break;\r
- \r
- case TemplateArgument::Type:\r
- ArgInfos[i] = TemplateArgumentLocInfo(\r
- Context.getTrivialTypeSourceInfo(Args[i].getAsType(), \r
- Loc));\r
- break;\r
-\r
- case TemplateArgument::Template:\r
- case TemplateArgument::TemplateExpansion: {\r
- NestedNameSpecifierLocBuilder Builder;\r
- TemplateName Template = Args[i].getAsTemplate();\r
- if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())\r
- Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);\r
- else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())\r
- Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);\r
- \r
- ArgInfos[i] = TemplateArgumentLocInfo(\r
- Builder.getWithLocInContext(Context),\r
- Loc, \r
- Args[i].getKind() == TemplateArgument::Template\r
- ? SourceLocation()\r
- : Loc);\r
- break;\r
- }\r
-\r
- case TemplateArgument::Pack:\r
- ArgInfos[i] = TemplateArgumentLocInfo();\r
- break;\r
- }\r
- }\r
-}\r
+//===--- 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;
+ }
+ }
+}
-//===--- CGDebugInfo.cpp - Emit Debug Information for a Module ------------===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This coordinates the debug information generation while generating code.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "CGDebugInfo.h"\r
-#include "CGBlocks.h"\r
-#include "CGObjCRuntime.h"\r
-#include "CodeGenFunction.h"\r
-#include "CodeGenModule.h"\r
-#include "clang/AST/ASTContext.h"\r
-#include "clang/AST/DeclFriend.h"\r
-#include "clang/AST/DeclObjC.h"\r
-#include "clang/AST/DeclTemplate.h"\r
-#include "clang/AST/Expr.h"\r
-#include "clang/AST/RecordLayout.h"\r
-#include "clang/Basic/FileManager.h"\r
-#include "clang/Basic/SourceManager.h"\r
-#include "clang/Basic/Version.h"\r
-#include "clang/Frontend/CodeGenOptions.h"\r
-#include "llvm/ADT/SmallVector.h"\r
-#include "llvm/ADT/StringExtras.h"\r
-#include "llvm/Constants.h"\r
-#include "llvm/DataLayout.h"\r
-#include "llvm/DerivedTypes.h"\r
-#include "llvm/Instructions.h"\r
-#include "llvm/Intrinsics.h"\r
-#include "llvm/Module.h"\r
-#include "llvm/Support/Dwarf.h"\r
-#include "llvm/Support/FileSystem.h"\r
-using namespace clang;\r
-using namespace clang::CodeGen;\r
-\r
-CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)\r
- : CGM(CGM), DBuilder(CGM.getModule()),\r
- BlockLiteralGenericSet(false) {\r
- CreateCompileUnit();\r
-}\r
-\r
-CGDebugInfo::~CGDebugInfo() {\r
- assert(LexicalBlockStack.empty() &&\r
- "Region stack mismatch, stack not empty!");\r
-}\r
-\r
-void CGDebugInfo::setLocation(SourceLocation Loc) {\r
- // If the new location isn't valid return.\r
- if (!Loc.isValid()) return;\r
-\r
- CurLoc = CGM.getContext().getSourceManager().getExpansionLoc(Loc);\r
-\r
- // If we've changed files in the middle of a lexical scope go ahead\r
- // and create a new lexical scope with file node if it's different\r
- // from the one in the scope.\r
- if (LexicalBlockStack.empty()) return;\r
-\r
- SourceManager &SM = CGM.getContext().getSourceManager();\r
- PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);\r
- PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc);\r
-\r
- if (PCLoc.isInvalid() || PPLoc.isInvalid() ||\r
- !strcmp(PPLoc.getFilename(), PCLoc.getFilename()))\r
- return;\r
-\r
- llvm::MDNode *LB = LexicalBlockStack.back();\r
- llvm::DIScope Scope = llvm::DIScope(LB);\r
- if (Scope.isLexicalBlockFile()) {\r
- llvm::DILexicalBlockFile LBF = llvm::DILexicalBlockFile(LB);\r
- llvm::DIDescriptor D\r
- = DBuilder.createLexicalBlockFile(LBF.getScope(),\r
- getOrCreateFile(CurLoc));\r
- llvm::MDNode *N = D;\r
- LexicalBlockStack.pop_back();\r
- LexicalBlockStack.push_back(N);\r
- } else if (Scope.isLexicalBlock()) {\r
- llvm::DIDescriptor D\r
- = DBuilder.createLexicalBlockFile(Scope, getOrCreateFile(CurLoc));\r
- llvm::MDNode *N = D;\r
- LexicalBlockStack.pop_back();\r
- LexicalBlockStack.push_back(N);\r
- }\r
-}\r
-\r
-/// getContextDescriptor - Get context info for the decl.\r
-llvm::DIDescriptor CGDebugInfo::getContextDescriptor(const Decl *Context) {\r
- if (!Context)\r
- return TheCU;\r
-\r
- llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator\r
- I = RegionMap.find(Context);\r
- if (I != RegionMap.end()) {\r
- llvm::Value *V = I->second;\r
- return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));\r
- }\r
-\r
- // Check namespace.\r
- if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context))\r
- return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl));\r
-\r
- if (const RecordDecl *RDecl = dyn_cast<RecordDecl>(Context)) {\r
- if (!RDecl->isDependentType()) {\r
- llvm::DIType Ty = getOrCreateType(CGM.getContext().getTypeDeclType(RDecl),\r
- getOrCreateMainFile());\r
- return llvm::DIDescriptor(Ty);\r
- }\r
- }\r
- return TheCU;\r
-}\r
-\r
-/// getFunctionName - Get function name for the given FunctionDecl. If the\r
-/// name is constructred on demand (e.g. C++ destructor) then the name\r
-/// is stored on the side.\r
-StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {\r
- assert (FD && "Invalid FunctionDecl!");\r
- IdentifierInfo *FII = FD->getIdentifier();\r
- FunctionTemplateSpecializationInfo *Info\r
- = FD->getTemplateSpecializationInfo();\r
- if (!Info && FII)\r
- return FII->getName();\r
-\r
- // Otherwise construct human readable name for debug info.\r
- std::string NS = FD->getNameAsString();\r
-\r
- // Add any template specialization args.\r
- if (Info) {\r
- const TemplateArgumentList *TArgs = Info->TemplateArguments;\r
- const TemplateArgument *Args = TArgs->data();\r
- unsigned NumArgs = TArgs->size();\r
- PrintingPolicy Policy(CGM.getLangOpts());\r
- NS += TemplateSpecializationType::PrintTemplateArgumentList(Args,\r
- NumArgs,\r
- Policy);\r
- }\r
-\r
- // Copy this name on the side and use its reference.\r
- char *StrPtr = DebugInfoNames.Allocate<char>(NS.length());\r
- memcpy(StrPtr, NS.data(), NS.length());\r
- return StringRef(StrPtr, NS.length());\r
-}\r
-\r
-StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {\r
- SmallString<256> MethodName;\r
- llvm::raw_svector_ostream OS(MethodName);\r
- OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';\r
- const DeclContext *DC = OMD->getDeclContext();\r
- if (const ObjCImplementationDecl *OID = \r
- dyn_cast<const ObjCImplementationDecl>(DC)) {\r
- OS << OID->getName();\r
- } else if (const ObjCInterfaceDecl *OID = \r
- dyn_cast<const ObjCInterfaceDecl>(DC)) {\r
- OS << OID->getName();\r
- } else if (const ObjCCategoryImplDecl *OCD = \r
- dyn_cast<const ObjCCategoryImplDecl>(DC)){\r
- OS << ((const NamedDecl *)OCD)->getIdentifier()->getNameStart() << '(' <<\r
- OCD->getIdentifier()->getNameStart() << ')';\r
- }\r
- OS << ' ' << OMD->getSelector().getAsString() << ']';\r
-\r
- char *StrPtr = DebugInfoNames.Allocate<char>(OS.tell());\r
- memcpy(StrPtr, MethodName.begin(), OS.tell());\r
- return StringRef(StrPtr, OS.tell());\r
-}\r
-\r
-/// getSelectorName - Return selector name. This is used for debugging\r
-/// info.\r
-StringRef CGDebugInfo::getSelectorName(Selector S) {\r
- const std::string &SName = S.getAsString();\r
- char *StrPtr = DebugInfoNames.Allocate<char>(SName.size());\r
- memcpy(StrPtr, SName.data(), SName.size());\r
- return StringRef(StrPtr, SName.size());\r
-}\r
-\r
-/// getClassName - Get class name including template argument list.\r
-StringRef \r
-CGDebugInfo::getClassName(const RecordDecl *RD) {\r
- const ClassTemplateSpecializationDecl *Spec\r
- = dyn_cast<ClassTemplateSpecializationDecl>(RD);\r
- if (!Spec)\r
- return RD->getName();\r
-\r
- const TemplateArgument *Args;\r
- unsigned NumArgs;\r
- if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {\r
- const TemplateSpecializationType *TST =\r
- cast<TemplateSpecializationType>(TAW->getType());\r
- Args = TST->getArgs();\r
- NumArgs = TST->getNumArgs();\r
- } else {\r
- const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();\r
- Args = TemplateArgs.data();\r
- NumArgs = TemplateArgs.size();\r
- }\r
- StringRef Name = RD->getIdentifier()->getName();\r
- PrintingPolicy Policy(CGM.getLangOpts());\r
- std::string TemplateArgList =\r
- TemplateSpecializationType::PrintTemplateArgumentList(Args, NumArgs, Policy);\r
-\r
- // Copy this name on the side and use its reference.\r
- size_t Length = Name.size() + TemplateArgList.size();\r
- char *StrPtr = DebugInfoNames.Allocate<char>(Length);\r
- memcpy(StrPtr, Name.data(), Name.size());\r
- memcpy(StrPtr + Name.size(), TemplateArgList.data(), TemplateArgList.size());\r
- return StringRef(StrPtr, Length);\r
-}\r
-\r
-/// getOrCreateFile - Get the file debug info descriptor for the input location.\r
-llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {\r
- if (!Loc.isValid())\r
- // If Location is not valid then use main input file.\r
- return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());\r
-\r
- SourceManager &SM = CGM.getContext().getSourceManager();\r
- PresumedLoc PLoc = SM.getPresumedLoc(Loc);\r
-\r
- if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty())\r
- // If the location is not valid then use main input file.\r
- return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());\r
-\r
- // Cache the results.\r
- const char *fname = PLoc.getFilename();\r
- llvm::DenseMap<const char *, llvm::WeakVH>::iterator it =\r
- DIFileCache.find(fname);\r
-\r
- if (it != DIFileCache.end()) {\r
- // Verify that the information still exists.\r
- if (llvm::Value *V = it->second)\r
- return llvm::DIFile(cast<llvm::MDNode>(V));\r
- }\r
-\r
- llvm::DIFile F = DBuilder.createFile(PLoc.getFilename(), getCurrentDirname());\r
-\r
- DIFileCache[fname] = F;\r
- return F;\r
-}\r
-\r
-/// getOrCreateMainFile - Get the file info for main compile unit.\r
-llvm::DIFile CGDebugInfo::getOrCreateMainFile() {\r
- return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());\r
-}\r
-\r
-/// getLineNumber - Get line number for the location. If location is invalid\r
-/// then use current location.\r
-unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {\r
- if (Loc.isInvalid() && CurLoc.isInvalid())\r
- return 0;\r
- SourceManager &SM = CGM.getContext().getSourceManager();\r
- PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc);\r
- return PLoc.isValid()? PLoc.getLine() : 0;\r
-}\r
-\r
-/// getColumnNumber - Get column number for the location.\r
-unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) {\r
- // We may not want column information at all.\r
- if (!CGM.getCodeGenOpts().DebugColumnInfo)\r
- return 0;\r
-\r
- // If the location is invalid then use the current column.\r
- if (Loc.isInvalid() && CurLoc.isInvalid())\r
- return 0;\r
- SourceManager &SM = CGM.getContext().getSourceManager();\r
- PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc);\r
- return PLoc.isValid()? PLoc.getColumn() : 0;\r
-}\r
-\r
-StringRef CGDebugInfo::getCurrentDirname() {\r
- if (!CGM.getCodeGenOpts().DebugCompilationDir.empty())\r
- return CGM.getCodeGenOpts().DebugCompilationDir;\r
-\r
- if (!CWDName.empty())\r
- return CWDName;\r
- SmallString<256> CWD;\r
- llvm::sys::fs::current_path(CWD);\r
- char *CompDirnamePtr = DebugInfoNames.Allocate<char>(CWD.size());\r
- memcpy(CompDirnamePtr, CWD.data(), CWD.size());\r
- return CWDName = StringRef(CompDirnamePtr, CWD.size());\r
-}\r
-\r
-/// CreateCompileUnit - Create new compile unit.\r
-void CGDebugInfo::CreateCompileUnit() {\r
-\r
- // Get absolute path name.\r
- SourceManager &SM = CGM.getContext().getSourceManager();\r
- std::string MainFileName = CGM.getCodeGenOpts().MainFileName;\r
- if (MainFileName.empty())\r
- MainFileName = "<unknown>";\r
-\r
- // The main file name provided via the "-main-file-name" option contains just\r
- // the file name itself with no path information. This file name may have had\r
- // a relative path, so we look into the actual file entry for the main\r
- // file to determine the real absolute path for the file.\r
- std::string MainFileDir;\r
- if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {\r
- MainFileDir = MainFile->getDir()->getName();\r
- if (MainFileDir != ".")\r
- MainFileName = MainFileDir + "/" + MainFileName;\r
- }\r
-\r
- // Save filename string.\r
- char *FilenamePtr = DebugInfoNames.Allocate<char>(MainFileName.length());\r
- memcpy(FilenamePtr, MainFileName.c_str(), MainFileName.length());\r
- StringRef Filename(FilenamePtr, MainFileName.length());\r
- \r
- unsigned LangTag;\r
- const LangOptions &LO = CGM.getLangOpts();\r
- if (LO.CPlusPlus) {\r
- if (LO.ObjC1)\r
- LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;\r
- else\r
- LangTag = llvm::dwarf::DW_LANG_C_plus_plus;\r
- } else if (LO.ObjC1) {\r
- LangTag = llvm::dwarf::DW_LANG_ObjC;\r
- } else if (LO.C99) {\r
- LangTag = llvm::dwarf::DW_LANG_C99;\r
- } else {\r
- LangTag = llvm::dwarf::DW_LANG_C89;\r
- }\r
-\r
- std::string Producer = getClangFullVersion();\r
-\r
- // Figure out which version of the ObjC runtime we have.\r
- unsigned RuntimeVers = 0;\r
- if (LO.ObjC1)\r
- RuntimeVers = LO.ObjCRuntime.isNonFragile() ? 2 : 1;\r
-\r
- // Create new compile unit.\r
- DBuilder.createCompileUnit(\r
- LangTag, Filename, getCurrentDirname(),\r
- Producer,\r
- LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers);\r
- // FIXME - Eliminate TheCU.\r
- TheCU = llvm::DICompileUnit(DBuilder.getCU());\r
-}\r
-\r
-/// CreateType - Get the Basic type from the cache or create a new\r
-/// one if necessary.\r
-llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {\r
- unsigned Encoding = 0;\r
- StringRef BTName;\r
- switch (BT->getKind()) {\r
-#define BUILTIN_TYPE(Id, SingletonId)\r
-#define PLACEHOLDER_TYPE(Id, SingletonId) \\r
- case BuiltinType::Id:\r
-#include "clang/AST/BuiltinTypes.def"\r
- case BuiltinType::Dependent:\r
- llvm_unreachable("Unexpected builtin type");\r
- case BuiltinType::NullPtr:\r
- return DBuilder.\r
- createNullPtrType(BT->getName(CGM.getLangOpts()));\r
- case BuiltinType::Void:\r
- return llvm::DIType();\r
- case BuiltinType::ObjCClass:\r
- if (ClassTy.Verify())\r
- return ClassTy;\r
- ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,\r
- "objc_class", TheCU,\r
- getOrCreateMainFile(), 0);\r
- return ClassTy;\r
- case BuiltinType::ObjCId: {\r
- // typedef struct objc_class *Class;\r
- // typedef struct objc_object {\r
- // Class isa;\r
- // } *id;\r
-\r
- if (ObjTy.Verify())\r
- return ObjTy;\r
-\r
- if (!ClassTy.Verify())\r
- ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,\r
- "objc_class", TheCU,\r
- getOrCreateMainFile(), 0);\r
-\r
- unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);\r
- \r
- llvm::DIType ISATy = DBuilder.createPointerType(ClassTy, Size);\r
-\r
- llvm::DIType FwdTy = DBuilder.createStructType(TheCU, "objc_object", \r
- getOrCreateMainFile(),\r
- 0, 0, 0, 0,\r
- llvm::DIArray());\r
-\r
- llvm::TrackingVH<llvm::MDNode> ObjNode(FwdTy);\r
- SmallVector<llvm::Value *, 1> EltTys;\r
- llvm::DIType FieldTy = \r
- DBuilder.createMemberType(llvm::DIDescriptor(ObjNode), "isa",\r
- getOrCreateMainFile(), 0, Size,\r
- 0, 0, 0, ISATy);\r
- EltTys.push_back(FieldTy);\r
- llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);\r
-\r
- ObjNode->replaceOperandWith(10, Elements);\r
- ObjTy = llvm::DIType(ObjNode);\r
- return ObjTy;\r
- }\r
- case BuiltinType::ObjCSel: {\r
- if (SelTy.Verify())\r
- return SelTy;\r
- SelTy =\r
- DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,\r
- "objc_selector", TheCU, getOrCreateMainFile(),\r
- 0);\r
- return SelTy;\r
- }\r
-\r
- case BuiltinType::OCLImage1d:\r
- return getOrCreateStructPtrType("opencl_image1d_t",\r
- OCLImage1dDITy);\r
- case BuiltinType::OCLImage1dArray:\r
- return getOrCreateStructPtrType("opencl_image1d_array_t", \r
- OCLImage1dArrayDITy);\r
- case BuiltinType::OCLImage1dBuffer:\r
- return getOrCreateStructPtrType("opencl_image1d_buffer_t",\r
- OCLImage1dBufferDITy);\r
- case BuiltinType::OCLImage2d:\r
- return getOrCreateStructPtrType("opencl_image2d_t",\r
- OCLImage2dDITy);\r
- case BuiltinType::OCLImage2dArray:\r
- return getOrCreateStructPtrType("opencl_image2d_array_t",\r
- OCLImage2dArrayDITy);\r
- case BuiltinType::OCLImage3d:\r
- return getOrCreateStructPtrType("opencl_image3d_t",\r
- OCLImage3dDITy);\r
-\r
- case BuiltinType::UChar:\r
- case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break;\r
- case BuiltinType::Char_S:\r
- case BuiltinType::SChar: Encoding = llvm::dwarf::DW_ATE_signed_char; break;\r
- case BuiltinType::Char16:\r
- case BuiltinType::Char32: Encoding = llvm::dwarf::DW_ATE_UTF; break;\r
- case BuiltinType::UShort:\r
- case BuiltinType::UInt:\r
- case BuiltinType::UInt128:\r
- case BuiltinType::ULong:\r
- case BuiltinType::WChar_U:\r
- case BuiltinType::ULongLong: Encoding = llvm::dwarf::DW_ATE_unsigned; break;\r
- case BuiltinType::Short:\r
- case BuiltinType::Int:\r
- case BuiltinType::Int128:\r
- case BuiltinType::Long:\r
- case BuiltinType::WChar_S:\r
- case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break;\r
- case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break;\r
- case BuiltinType::Half:\r
- case BuiltinType::Float:\r
- case BuiltinType::LongDouble:\r
- case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break;\r
- }\r
-\r
- switch (BT->getKind()) {\r
- case BuiltinType::Long: BTName = "long int"; break;\r
- case BuiltinType::LongLong: BTName = "long long int"; break;\r
- case BuiltinType::ULong: BTName = "long unsigned int"; break;\r
- case BuiltinType::ULongLong: BTName = "long long unsigned int"; break;\r
- default:\r
- BTName = BT->getName(CGM.getLangOpts());\r
- break;\r
- }\r
- // Bit size, align and offset of the type.\r
- uint64_t Size = CGM.getContext().getTypeSize(BT);\r
- uint64_t Align = CGM.getContext().getTypeAlign(BT);\r
- llvm::DIType DbgTy = \r
- DBuilder.createBasicType(BTName, Size, Align, Encoding);\r
- return DbgTy;\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {\r
- // Bit size, align and offset of the type.\r
- unsigned Encoding = llvm::dwarf::DW_ATE_complex_float;\r
- if (Ty->isComplexIntegerType())\r
- Encoding = llvm::dwarf::DW_ATE_lo_user;\r
-\r
- uint64_t Size = CGM.getContext().getTypeSize(Ty);\r
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);\r
- llvm::DIType DbgTy = \r
- DBuilder.createBasicType("complex", Size, Align, Encoding);\r
-\r
- return DbgTy;\r
-}\r
-\r
-/// CreateCVRType - Get the qualified type from the cache or create\r
-/// a new one if necessary.\r
-llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {\r
- QualifierCollector Qc;\r
- const Type *T = Qc.strip(Ty);\r
-\r
- // Ignore these qualifiers for now.\r
- Qc.removeObjCGCAttr();\r
- Qc.removeAddressSpace();\r
- Qc.removeObjCLifetime();\r
-\r
- // We will create one Derived type for one qualifier and recurse to handle any\r
- // additional ones.\r
- unsigned Tag;\r
- if (Qc.hasConst()) {\r
- Tag = llvm::dwarf::DW_TAG_const_type;\r
- Qc.removeConst();\r
- } else if (Qc.hasVolatile()) {\r
- Tag = llvm::dwarf::DW_TAG_volatile_type;\r
- Qc.removeVolatile();\r
- } else if (Qc.hasRestrict()) {\r
- Tag = llvm::dwarf::DW_TAG_restrict_type;\r
- Qc.removeRestrict();\r
- } else {\r
- assert(Qc.empty() && "Unknown type qualifier for debug info");\r
- return getOrCreateType(QualType(T, 0), Unit);\r
- }\r
-\r
- llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);\r
-\r
- // No need to fill in the Name, Line, Size, Alignment, Offset in case of\r
- // CVR derived types.\r
- llvm::DIType DbgTy = DBuilder.createQualifiedType(Tag, FromTy);\r
- \r
- return DbgTy;\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,\r
- llvm::DIFile Unit) {\r
- llvm::DIType DbgTy =\r
- CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty, \r
- Ty->getPointeeType(), Unit);\r
- return DbgTy;\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,\r
- llvm::DIFile Unit) {\r
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty, \r
- Ty->getPointeeType(), Unit);\r
-}\r
-\r
-// Creates a forward declaration for a RecordDecl in the given context.\r
-llvm::DIType CGDebugInfo::createRecordFwdDecl(const RecordDecl *RD,\r
- llvm::DIDescriptor Ctx) {\r
- llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());\r
- unsigned Line = getLineNumber(RD->getLocation());\r
- StringRef RDName = getClassName(RD);\r
-\r
- unsigned Tag = 0;\r
- if (RD->isStruct() || RD->isInterface())\r
- Tag = llvm::dwarf::DW_TAG_structure_type;\r
- else if (RD->isUnion())\r
- Tag = llvm::dwarf::DW_TAG_union_type;\r
- else {\r
- assert(RD->isClass());\r
- Tag = llvm::dwarf::DW_TAG_class_type;\r
- }\r
-\r
- // Create the type.\r
- return DBuilder.createForwardDecl(Tag, RDName, Ctx, DefUnit, Line);\r
-}\r
-\r
-// Walk up the context chain and create forward decls for record decls,\r
-// and normal descriptors for namespaces.\r
-llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) {\r
- if (!Context)\r
- return TheCU;\r
-\r
- // See if we already have the parent.\r
- llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator\r
- I = RegionMap.find(Context);\r
- if (I != RegionMap.end()) {\r
- llvm::Value *V = I->second;\r
- return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));\r
- }\r
- \r
- // Check namespace.\r
- if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context))\r
- return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl));\r
-\r
- if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) {\r
- if (!RD->isDependentType()) {\r
- llvm::DIType Ty = getOrCreateLimitedType(CGM.getContext().getTypeDeclType(RD),\r
- getOrCreateMainFile());\r
- return llvm::DIDescriptor(Ty);\r
- }\r
- }\r
- return TheCU;\r
-}\r
-\r
-/// CreatePointeeType - Create Pointee type. If Pointee is a record\r
-/// then emit record's fwd if debug info size reduction is enabled.\r
-llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy,\r
- llvm::DIFile Unit) {\r
- if (CGM.getCodeGenOpts().getDebugInfo() != CodeGenOptions::LimitedDebugInfo)\r
- return getOrCreateType(PointeeTy, Unit);\r
-\r
- // Limit debug info for the pointee type.\r
-\r
- // If we have an existing type, use that, it's still smaller than creating\r
- // a new type.\r
- llvm::DIType Ty = getTypeOrNull(PointeeTy);\r
- if (Ty.Verify()) return Ty;\r
-\r
- // Handle qualifiers.\r
- if (PointeeTy.hasLocalQualifiers())\r
- return CreateQualifiedType(PointeeTy, Unit);\r
-\r
- if (const RecordType *RTy = dyn_cast<RecordType>(PointeeTy)) {\r
- RecordDecl *RD = RTy->getDecl();\r
- llvm::DIDescriptor FDContext =\r
- getContextDescriptor(cast<Decl>(RD->getDeclContext()));\r
- llvm::DIType RetTy = createRecordFwdDecl(RD, FDContext);\r
- TypeCache[QualType(RTy, 0).getAsOpaquePtr()] = RetTy;\r
- return RetTy;\r
- }\r
- return getOrCreateType(PointeeTy, Unit);\r
-\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,\r
- const Type *Ty, \r
- QualType PointeeTy,\r
- llvm::DIFile Unit) {\r
- if (Tag == llvm::dwarf::DW_TAG_reference_type ||\r
- Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)\r
- return DBuilder.createReferenceType(Tag,\r
- CreatePointeeType(PointeeTy, Unit));\r
- \r
- // Bit size, align and offset of the type.\r
- // Size is always the size of a pointer. We can't use getTypeSize here\r
- // because that does not return the correct value for references.\r
- unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);\r
- uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS);\r
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);\r
-\r
- return DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit),\r
- Size, Align);\r
-}\r
-\r
-llvm::DIType CGDebugInfo::getOrCreateStructPtrType(StringRef Name, llvm::DIType &Cache) {\r
- if (Cache.Verify())\r
- return Cache;\r
- Cache =\r
- DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,\r
- Name, TheCU, getOrCreateMainFile(),\r
- 0);\r
- unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);\r
- Cache = DBuilder.createPointerType(Cache, Size);\r
- return Cache;\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,\r
- llvm::DIFile Unit) {\r
- if (BlockLiteralGenericSet)\r
- return BlockLiteralGeneric;\r
-\r
- SmallVector<llvm::Value *, 8> EltTys;\r
- llvm::DIType FieldTy;\r
- QualType FType;\r
- uint64_t FieldSize, FieldOffset;\r
- unsigned FieldAlign;\r
- llvm::DIArray Elements;\r
- llvm::DIType EltTy, DescTy;\r
-\r
- FieldOffset = 0;\r
- FType = CGM.getContext().UnsignedLongTy;\r
- EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset));\r
- EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset));\r
-\r
- Elements = DBuilder.getOrCreateArray(EltTys);\r
- EltTys.clear();\r
-\r
- unsigned Flags = llvm::DIDescriptor::FlagAppleBlock;\r
- unsigned LineNo = getLineNumber(CurLoc);\r
-\r
- EltTy = DBuilder.createStructType(Unit, "__block_descriptor",\r
- Unit, LineNo, FieldOffset, 0,\r
- Flags, Elements);\r
-\r
- // Bit size, align and offset of the type.\r
- uint64_t Size = CGM.getContext().getTypeSize(Ty);\r
-\r
- DescTy = DBuilder.createPointerType(EltTy, Size);\r
-\r
- FieldOffset = 0;\r
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);\r
- EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));\r
- FType = CGM.getContext().IntTy;\r
- EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));\r
- EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset));\r
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);\r
- EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset));\r
-\r
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);\r
- FieldTy = DescTy;\r
- FieldSize = CGM.getContext().getTypeSize(Ty);\r
- FieldAlign = CGM.getContext().getTypeAlign(Ty);\r
- FieldTy = DBuilder.createMemberType(Unit, "__descriptor", Unit,\r
- LineNo, FieldSize, FieldAlign,\r
- FieldOffset, 0, FieldTy);\r
- EltTys.push_back(FieldTy);\r
-\r
- FieldOffset += FieldSize;\r
- Elements = DBuilder.getOrCreateArray(EltTys);\r
-\r
- EltTy = DBuilder.createStructType(Unit, "__block_literal_generic",\r
- Unit, LineNo, FieldOffset, 0,\r
- Flags, Elements);\r
-\r
- BlockLiteralGenericSet = true;\r
- BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size);\r
- return BlockLiteralGeneric;\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit) {\r
- // Typedefs are derived from some other type. If we have a typedef of a\r
- // typedef, make sure to emit the whole chain.\r
- llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);\r
- if (!Src.Verify())\r
- return llvm::DIType();\r
- // We don't set size information, but do specify where the typedef was\r
- // declared.\r
- unsigned Line = getLineNumber(Ty->getDecl()->getLocation());\r
- const TypedefNameDecl *TyDecl = Ty->getDecl();\r
- \r
- llvm::DIDescriptor TypedefContext =\r
- getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext()));\r
- \r
- return\r
- DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, TypedefContext);\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,\r
- llvm::DIFile Unit) {\r
- SmallVector<llvm::Value *, 16> EltTys;\r
-\r
- // Add the result type at least.\r
- EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit));\r
-\r
- // Set up remainder of arguments if there is a prototype.\r
- // FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'!\r
- if (isa<FunctionNoProtoType>(Ty))\r
- EltTys.push_back(DBuilder.createUnspecifiedParameter());\r
- else if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Ty)) {\r
- for (unsigned i = 0, e = FPT->getNumArgs(); i != e; ++i)\r
- EltTys.push_back(getOrCreateType(FPT->getArgType(i), Unit));\r
- }\r
-\r
- llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(EltTys);\r
- return DBuilder.createSubroutineType(Unit, EltTypeArray);\r
-}\r
-\r
-\r
-void CGDebugInfo::\r
-CollectRecordStaticVars(const RecordDecl *RD, llvm::DIType FwdDecl) {\r
- \r
- for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end();\r
- I != E; ++I)\r
- if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {\r
- if (V->getInit()) {\r
- const APValue *Value = V->evaluateValue();\r
- if (Value && Value->isInt()) {\r
- llvm::ConstantInt *CI\r
- = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());\r
- \r
- // Create the descriptor for static variable.\r
- llvm::DIFile VUnit = getOrCreateFile(V->getLocation());\r
- StringRef VName = V->getName();\r
- llvm::DIType VTy = getOrCreateType(V->getType(), VUnit);\r
- // Do not use DIGlobalVariable for enums.\r
- if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) {\r
- DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit,\r
- getLineNumber(V->getLocation()),\r
- VTy, true, CI);\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-llvm::DIType CGDebugInfo::createFieldType(StringRef name,\r
- QualType type,\r
- uint64_t sizeInBitsOverride,\r
- SourceLocation loc,\r
- AccessSpecifier AS,\r
- uint64_t offsetInBits,\r
- llvm::DIFile tunit,\r
- llvm::DIDescriptor scope) {\r
- llvm::DIType debugType = getOrCreateType(type, tunit);\r
-\r
- // Get the location for the field.\r
- llvm::DIFile file = getOrCreateFile(loc);\r
- unsigned line = getLineNumber(loc);\r
-\r
- uint64_t sizeInBits = 0;\r
- unsigned alignInBits = 0;\r
- if (!type->isIncompleteArrayType()) {\r
- llvm::tie(sizeInBits, alignInBits) = CGM.getContext().getTypeInfo(type);\r
-\r
- if (sizeInBitsOverride)\r
- sizeInBits = sizeInBitsOverride;\r
- }\r
-\r
- unsigned flags = 0;\r
- if (AS == clang::AS_private)\r
- flags |= llvm::DIDescriptor::FlagPrivate;\r
- else if (AS == clang::AS_protected)\r
- flags |= llvm::DIDescriptor::FlagProtected;\r
-\r
- return DBuilder.createMemberType(scope, name, file, line, sizeInBits,\r
- alignInBits, offsetInBits, flags, debugType);\r
-}\r
-\r
-/// CollectRecordFields - A helper function to collect debug info for\r
-/// record fields. This is used while creating debug info entry for a Record.\r
-void CGDebugInfo::\r
-CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,\r
- SmallVectorImpl<llvm::Value *> &elements,\r
- llvm::DIType RecordTy) {\r
- unsigned fieldNo = 0;\r
- const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);\r
- const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(record);\r
-\r
- // For C++11 Lambdas a Field will be the same as a Capture, but the Capture\r
- // has the name and the location of the variable so we should iterate over\r
- // both concurrently.\r
- if (CXXDecl && CXXDecl->isLambda()) {\r
- RecordDecl::field_iterator Field = CXXDecl->field_begin();\r
- unsigned fieldno = 0;\r
- for (CXXRecordDecl::capture_const_iterator I = CXXDecl->captures_begin(),\r
- E = CXXDecl->captures_end(); I != E; ++I, ++Field, ++fieldno) {\r
- const LambdaExpr::Capture C = *I;\r
- if (C.capturesVariable()) {\r
- VarDecl *V = C.getCapturedVar();\r
- llvm::DIFile VUnit = getOrCreateFile(C.getLocation());\r
- StringRef VName = V->getName();\r
- uint64_t SizeInBitsOverride = 0;\r
- if (Field->isBitField()) {\r
- SizeInBitsOverride = Field->getBitWidthValue(CGM.getContext());\r
- assert(SizeInBitsOverride && "found named 0-width bitfield");\r
- }\r
- llvm::DIType fieldType\r
- = createFieldType(VName, Field->getType(), SizeInBitsOverride, C.getLocation(),\r
- Field->getAccess(), layout.getFieldOffset(fieldno),\r
- VUnit, RecordTy);\r
- elements.push_back(fieldType);\r
- } else {\r
- // TODO: Need to handle 'this' in some way by probably renaming the\r
- // this of the lambda class and having a field member of 'this' or\r
- // by using AT_object_pointer for the function and having that be\r
- // used as 'this' for semantic references.\r
- assert(C.capturesThis() && "Field that isn't captured and isn't this?");\r
- FieldDecl *f = *Field;\r
- llvm::DIFile VUnit = getOrCreateFile(f->getLocation());\r
- QualType type = f->getType();\r
- llvm::DIType fieldType\r
- = createFieldType("this", type, 0, f->getLocation(), f->getAccess(),\r
- layout.getFieldOffset(fieldNo), VUnit, RecordTy);\r
-\r
- elements.push_back(fieldType);\r
- }\r
- }\r
- } else {\r
- bool IsMsStruct = record->isMsStruct(CGM.getContext());\r
- const FieldDecl *LastFD = 0;\r
- for (RecordDecl::field_iterator I = record->field_begin(),\r
- E = record->field_end();\r
- I != E; ++I, ++fieldNo) {\r
- FieldDecl *field = *I;\r
-\r
- if (IsMsStruct) {\r
- // Zero-length bitfields following non-bitfield members are ignored\r
- if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD)) {\r
- --fieldNo;\r
- continue;\r
- }\r
- LastFD = field;\r
- }\r
-\r
- StringRef name = field->getName();\r
- QualType type = field->getType();\r
-\r
- // Ignore unnamed fields unless they're anonymous structs/unions.\r
- if (name.empty() && !type->isRecordType()) {\r
- LastFD = field;\r
- continue;\r
- }\r
-\r
- uint64_t SizeInBitsOverride = 0;\r
- if (field->isBitField()) {\r
- SizeInBitsOverride = field->getBitWidthValue(CGM.getContext());\r
- assert(SizeInBitsOverride && "found named 0-width bitfield");\r
- }\r
-\r
- llvm::DIType fieldType\r
- = createFieldType(name, type, SizeInBitsOverride,\r
- field->getLocation(), field->getAccess(),\r
- layout.getFieldOffset(fieldNo), tunit, RecordTy);\r
-\r
- elements.push_back(fieldType);\r
- }\r
- }\r
-}\r
-\r
-/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This\r
-/// function type is not updated to include implicit "this" pointer. Use this\r
-/// routine to get a method type which includes "this" pointer.\r
-llvm::DIType\r
-CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,\r
- llvm::DIFile Unit) {\r
- llvm::DIType FnTy\r
- = getOrCreateType(QualType(Method->getType()->getAs<FunctionProtoType>(),\r
- 0),\r
- Unit);\r
-\r
- // Add "this" pointer.\r
- llvm::DIArray Args = llvm::DICompositeType(FnTy).getTypeArray();\r
- assert (Args.getNumElements() && "Invalid number of arguments!");\r
-\r
- SmallVector<llvm::Value *, 16> Elts;\r
-\r
- // First element is always return type. For 'void' functions it is NULL.\r
- Elts.push_back(Args.getElement(0));\r
-\r
- if (!Method->isStatic()) {\r
- // "this" pointer is always first argument.\r
- QualType ThisPtr = Method->getThisType(CGM.getContext());\r
-\r
- const CXXRecordDecl *RD = Method->getParent();\r
- if (isa<ClassTemplateSpecializationDecl>(RD)) {\r
- // Create pointer type directly in this case.\r
- const PointerType *ThisPtrTy = cast<PointerType>(ThisPtr);\r
- QualType PointeeTy = ThisPtrTy->getPointeeType();\r
- unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);\r
- uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS);\r
- uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy);\r
- llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit);\r
- llvm::DIType ThisPtrType = DBuilder.createPointerType(PointeeType, Size, Align);\r
- TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;\r
- // TODO: This and the artificial type below are misleading, the\r
- // types aren't artificial the argument is, but the current\r
- // metadata doesn't represent that.\r
- ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);\r
- Elts.push_back(ThisPtrType);\r
- } else {\r
- llvm::DIType ThisPtrType = getOrCreateType(ThisPtr, Unit);\r
- TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;\r
- ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);\r
- Elts.push_back(ThisPtrType);\r
- }\r
- }\r
-\r
- // Copy rest of the arguments.\r
- for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i)\r
- Elts.push_back(Args.getElement(i));\r
-\r
- llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);\r
-\r
- return DBuilder.createSubroutineType(Unit, EltTypeArray);\r
-}\r
-\r
-/// isFunctionLocalClass - Return true if CXXRecordDecl is defined \r
-/// inside a function.\r
-static bool isFunctionLocalClass(const CXXRecordDecl *RD) {\r
- if (const CXXRecordDecl *NRD = dyn_cast<CXXRecordDecl>(RD->getDeclContext()))\r
- return isFunctionLocalClass(NRD);\r
- if (isa<FunctionDecl>(RD->getDeclContext()))\r
- return true;\r
- return false;\r
-}\r
-\r
-/// CreateCXXMemberFunction - A helper function to create a DISubprogram for\r
-/// a single member function GlobalDecl.\r
-llvm::DISubprogram\r
-CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,\r
- llvm::DIFile Unit,\r
- llvm::DIType RecordTy) {\r
- bool IsCtorOrDtor = \r
- isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);\r
- \r
- StringRef MethodName = getFunctionName(Method);\r
- llvm::DIType MethodTy = getOrCreateMethodType(Method, Unit);\r
-\r
- // Since a single ctor/dtor corresponds to multiple functions, it doesn't\r
- // make sense to give a single ctor/dtor a linkage name.\r
- StringRef MethodLinkageName;\r
- if (!IsCtorOrDtor && !isFunctionLocalClass(Method->getParent()))\r
- MethodLinkageName = CGM.getMangledName(Method);\r
-\r
- // Get the location for the method.\r
- llvm::DIFile MethodDefUnit = getOrCreateFile(Method->getLocation());\r
- unsigned MethodLine = getLineNumber(Method->getLocation());\r
-\r
- // Collect virtual method info.\r
- llvm::DIType ContainingType;\r
- unsigned Virtuality = 0; \r
- unsigned VIndex = 0;\r
- \r
- if (Method->isVirtual()) {\r
- if (Method->isPure())\r
- Virtuality = llvm::dwarf::DW_VIRTUALITY_pure_virtual;\r
- else\r
- Virtuality = llvm::dwarf::DW_VIRTUALITY_virtual;\r
- \r
- // It doesn't make sense to give a virtual destructor a vtable index,\r
- // since a single destructor has two entries in the vtable.\r
- if (!isa<CXXDestructorDecl>(Method))\r
- VIndex = CGM.getVTableContext().getMethodVTableIndex(Method);\r
- ContainingType = RecordTy;\r
- }\r
-\r
- unsigned Flags = 0;\r
- if (Method->isImplicit())\r
- Flags |= llvm::DIDescriptor::FlagArtificial;\r
- AccessSpecifier Access = Method->getAccess();\r
- if (Access == clang::AS_private)\r
- Flags |= llvm::DIDescriptor::FlagPrivate;\r
- else if (Access == clang::AS_protected)\r
- Flags |= llvm::DIDescriptor::FlagProtected;\r
- if (const CXXConstructorDecl *CXXC = dyn_cast<CXXConstructorDecl>(Method)) {\r
- if (CXXC->isExplicit())\r
- Flags |= llvm::DIDescriptor::FlagExplicit;\r
- } else if (const CXXConversionDecl *CXXC = \r
- dyn_cast<CXXConversionDecl>(Method)) {\r
- if (CXXC->isExplicit())\r
- Flags |= llvm::DIDescriptor::FlagExplicit;\r
- }\r
- if (Method->hasPrototype())\r
- Flags |= llvm::DIDescriptor::FlagPrototyped;\r
-\r
- llvm::DIArray TParamsArray = CollectFunctionTemplateParams(Method, Unit);\r
- llvm::DISubprogram SP =\r
- DBuilder.createMethod(RecordTy, MethodName, MethodLinkageName, \r
- MethodDefUnit, MethodLine,\r
- MethodTy, /*isLocalToUnit=*/false, \r
- /* isDefinition=*/ false,\r
- Virtuality, VIndex, ContainingType,\r
- Flags, CGM.getLangOpts().Optimize, NULL,\r
- TParamsArray);\r
- \r
- SPCache[Method->getCanonicalDecl()] = llvm::WeakVH(SP);\r
-\r
- return SP;\r
-}\r
-\r
-/// CollectCXXMemberFunctions - A helper function to collect debug info for\r
-/// C++ member functions. This is used while creating debug info entry for \r
-/// a Record.\r
-void CGDebugInfo::\r
-CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,\r
- SmallVectorImpl<llvm::Value *> &EltTys,\r
- llvm::DIType RecordTy) {\r
-\r
- // Since we want more than just the individual member decls if we\r
- // have templated functions iterate over every declaration to gather\r
- // the functions.\r
- for(DeclContext::decl_iterator I = RD->decls_begin(),\r
- E = RD->decls_end(); I != E; ++I) {\r
- Decl *D = *I;\r
- if (D->isImplicit() && !D->isUsed())\r
- continue;\r
-\r
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))\r
- EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));\r
- else if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))\r
- for (FunctionTemplateDecl::spec_iterator SI = FTD->spec_begin(),\r
- SE = FTD->spec_end(); SI != SE; ++SI)\r
- EltTys.push_back(CreateCXXMemberFunction(cast<CXXMethodDecl>(*SI), Unit,\r
- RecordTy));\r
- }\r
-} \r
-\r
-/// CollectCXXFriends - A helper function to collect debug info for\r
-/// C++ base classes. This is used while creating debug info entry for\r
-/// a Record.\r
-void CGDebugInfo::\r
-CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit,\r
- SmallVectorImpl<llvm::Value *> &EltTys,\r
- llvm::DIType RecordTy) {\r
- for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(),\r
- BE = RD->friend_end(); BI != BE; ++BI) {\r
- if ((*BI)->isUnsupportedFriend())\r
- continue;\r
- if (TypeSourceInfo *TInfo = (*BI)->getFriendType())\r
- EltTys.push_back(DBuilder.createFriend(RecordTy, \r
- getOrCreateType(TInfo->getType(), \r
- Unit)));\r
- }\r
-}\r
-\r
-/// CollectCXXBases - A helper function to collect debug info for\r
-/// C++ base classes. This is used while creating debug info entry for \r
-/// a Record.\r
-void CGDebugInfo::\r
-CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,\r
- SmallVectorImpl<llvm::Value *> &EltTys,\r
- llvm::DIType RecordTy) {\r
-\r
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);\r
- for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(),\r
- BE = RD->bases_end(); BI != BE; ++BI) {\r
- unsigned BFlags = 0;\r
- uint64_t BaseOffset;\r
- \r
- const CXXRecordDecl *Base =\r
- cast<CXXRecordDecl>(BI->getType()->getAs<RecordType>()->getDecl());\r
- \r
- if (BI->isVirtual()) {\r
- // virtual base offset offset is -ve. The code generator emits dwarf\r
- // expression where it expects +ve number.\r
- BaseOffset = \r
- 0 - CGM.getVTableContext()\r
- .getVirtualBaseOffsetOffset(RD, Base).getQuantity();\r
- BFlags = llvm::DIDescriptor::FlagVirtual;\r
- } else\r
- BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base));\r
- // FIXME: Inconsistent units for BaseOffset. It is in bytes when\r
- // BI->isVirtual() and bits when not.\r
- \r
- AccessSpecifier Access = BI->getAccessSpecifier();\r
- if (Access == clang::AS_private)\r
- BFlags |= llvm::DIDescriptor::FlagPrivate;\r
- else if (Access == clang::AS_protected)\r
- BFlags |= llvm::DIDescriptor::FlagProtected;\r
- \r
- llvm::DIType DTy = \r
- DBuilder.createInheritance(RecordTy, \r
- getOrCreateType(BI->getType(), Unit),\r
- BaseOffset, BFlags);\r
- EltTys.push_back(DTy);\r
- }\r
-}\r
-\r
-/// CollectTemplateParams - A helper function to collect template parameters.\r
-llvm::DIArray CGDebugInfo::\r
-CollectTemplateParams(const TemplateParameterList *TPList,\r
- const TemplateArgumentList &TAList,\r
- llvm::DIFile Unit) {\r
- SmallVector<llvm::Value *, 16> TemplateParams; \r
- for (unsigned i = 0, e = TAList.size(); i != e; ++i) {\r
- const TemplateArgument &TA = TAList[i];\r
- const NamedDecl *ND = TPList->getParam(i);\r
- if (TA.getKind() == TemplateArgument::Type) {\r
- llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit);\r
- llvm::DITemplateTypeParameter TTP =\r
- DBuilder.createTemplateTypeParameter(TheCU, ND->getName(), TTy);\r
- TemplateParams.push_back(TTP);\r
- } else if (TA.getKind() == TemplateArgument::Integral) {\r
- llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit);\r
- llvm::DITemplateValueParameter TVP =\r
- DBuilder.createTemplateValueParameter(TheCU, ND->getName(), TTy,\r
- TA.getAsIntegral().getZExtValue());\r
- TemplateParams.push_back(TVP); \r
- }\r
- }\r
- return DBuilder.getOrCreateArray(TemplateParams);\r
-}\r
-\r
-/// CollectFunctionTemplateParams - A helper function to collect debug\r
-/// info for function template parameters.\r
-llvm::DIArray CGDebugInfo::\r
-CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit) {\r
- if (FD->getTemplatedKind() ==\r
- FunctionDecl::TK_FunctionTemplateSpecialization) {\r
- const TemplateParameterList *TList =\r
- FD->getTemplateSpecializationInfo()->getTemplate()\r
- ->getTemplateParameters();\r
- return \r
- CollectTemplateParams(TList, *FD->getTemplateSpecializationArgs(), Unit);\r
- }\r
- return llvm::DIArray();\r
-}\r
-\r
-/// CollectCXXTemplateParams - A helper function to collect debug info for\r
-/// template parameters.\r
-llvm::DIArray CGDebugInfo::\r
-CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TSpecial,\r
- llvm::DIFile Unit) {\r
- llvm::PointerUnion<ClassTemplateDecl *,\r
- ClassTemplatePartialSpecializationDecl *>\r
- PU = TSpecial->getSpecializedTemplateOrPartial();\r
- \r
- TemplateParameterList *TPList = PU.is<ClassTemplateDecl *>() ?\r
- PU.get<ClassTemplateDecl *>()->getTemplateParameters() :\r
- PU.get<ClassTemplatePartialSpecializationDecl *>()->getTemplateParameters();\r
- const TemplateArgumentList &TAList = TSpecial->getTemplateInstantiationArgs();\r
- return CollectTemplateParams(TPList, TAList, Unit);\r
-}\r
-\r
-/// getOrCreateVTablePtrType - Return debug info descriptor for vtable.\r
-llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {\r
- if (VTablePtrType.isValid())\r
- return VTablePtrType;\r
-\r
- ASTContext &Context = CGM.getContext();\r
-\r
- /* Function type */\r
- llvm::Value *STy = getOrCreateType(Context.IntTy, Unit);\r
- llvm::DIArray SElements = DBuilder.getOrCreateArray(STy);\r
- llvm::DIType SubTy = DBuilder.createSubroutineType(Unit, SElements);\r
- unsigned Size = Context.getTypeSize(Context.VoidPtrTy);\r
- llvm::DIType vtbl_ptr_type = DBuilder.createPointerType(SubTy, Size, 0,\r
- "__vtbl_ptr_type");\r
- VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size);\r
- return VTablePtrType;\r
-}\r
-\r
-/// getVTableName - Get vtable name for the given Class.\r
-StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {\r
- // Construct gdb compatible name name.\r
- std::string Name = "_vptr$" + RD->getNameAsString();\r
-\r
- // Copy this name on the side and use its reference.\r
- char *StrPtr = DebugInfoNames.Allocate<char>(Name.length());\r
- memcpy(StrPtr, Name.data(), Name.length());\r
- return StringRef(StrPtr, Name.length());\r
-}\r
-\r
-\r
-/// CollectVTableInfo - If the C++ class has vtable info then insert appropriate\r
-/// debug info entry in EltTys vector.\r
-void CGDebugInfo::\r
-CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,\r
- SmallVectorImpl<llvm::Value *> &EltTys) {\r
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);\r
-\r
- // If there is a primary base then it will hold vtable info.\r
- if (RL.getPrimaryBase())\r
- return;\r
-\r
- // If this class is not dynamic then there is not any vtable info to collect.\r
- if (!RD->isDynamicClass())\r
- return;\r
-\r
- unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);\r
- llvm::DIType VPTR\r
- = DBuilder.createMemberType(Unit, getVTableName(RD), Unit,\r
- 0, Size, 0, 0, llvm::DIDescriptor::FlagArtificial,\r
- getOrCreateVTablePtrType(Unit));\r
- EltTys.push_back(VPTR);\r
-}\r
-\r
-/// getOrCreateRecordType - Emit record type's standalone debug info. \r
-llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy, \r
- SourceLocation Loc) {\r
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);\r
- llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc));\r
- return T;\r
-}\r
-\r
-/// getOrCreateInterfaceType - Emit an objective c interface type standalone\r
-/// debug info.\r
-llvm::DIType CGDebugInfo::getOrCreateInterfaceType(QualType D,\r
- SourceLocation Loc) {\r
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);\r
- llvm::DIType T = getOrCreateType(D, getOrCreateFile(Loc));\r
- DBuilder.retainType(T);\r
- return T;\r
-}\r
-\r
-/// CreateType - get structure or union type.\r
-llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {\r
- RecordDecl *RD = Ty->getDecl();\r
-\r
- // Get overall information about the record type for the debug info.\r
- llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());\r
-\r
- // Records and classes and unions can all be recursive. To handle them, we\r
- // first generate a debug descriptor for the struct as a forward declaration.\r
- // Then (if it is a definition) we go through and get debug info for all of\r
- // its members. Finally, we create a descriptor for the complete type (which\r
- // may refer to the forward decl if the struct is recursive) and replace all\r
- // uses of the forward declaration with the final definition.\r
-\r
- llvm::DIType FwdDecl = getOrCreateLimitedType(QualType(Ty, 0), DefUnit);\r
-\r
- if (FwdDecl.isForwardDecl())\r
- return FwdDecl;\r
-\r
- llvm::TrackingVH<llvm::MDNode> FwdDeclNode(FwdDecl);\r
-\r
- // Push the struct on region stack.\r
- LexicalBlockStack.push_back(FwdDeclNode);\r
- RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);\r
-\r
- // Add this to the completed types cache since we're completing it.\r
- CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;\r
-\r
- // Convert all the elements.\r
- SmallVector<llvm::Value *, 16> EltTys;\r
-\r
- // Note: The split of CXXDecl information here is intentional, the\r
- // gdb tests will depend on a certain ordering at printout. The debug\r
- // information offsets are still correct if we merge them all together\r
- // though.\r
- const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);\r
- if (CXXDecl) {\r
- CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl);\r
- CollectVTableInfo(CXXDecl, DefUnit, EltTys);\r
- }\r
-\r
- // Collect static variables with initializers and other fields.\r
- CollectRecordStaticVars(RD, FwdDecl);\r
- CollectRecordFields(RD, DefUnit, EltTys, FwdDecl);\r
- llvm::DIArray TParamsArray;\r
- if (CXXDecl) {\r
- CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl);\r
- CollectCXXFriends(CXXDecl, DefUnit, EltTys, FwdDecl);\r
- if (const ClassTemplateSpecializationDecl *TSpecial\r
- = dyn_cast<ClassTemplateSpecializationDecl>(RD))\r
- TParamsArray = CollectCXXTemplateParams(TSpecial, DefUnit);\r
- }\r
-\r
- LexicalBlockStack.pop_back();\r
- RegionMap.erase(Ty->getDecl());\r
-\r
- llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);\r
- // FIXME: Magic numbers ahoy! These should be changed when we\r
- // get some enums in llvm/Analysis/DebugInfo.h to refer to\r
- // them.\r
- if (RD->isUnion())\r
- FwdDeclNode->replaceOperandWith(10, Elements);\r
- else if (CXXDecl) {\r
- FwdDeclNode->replaceOperandWith(10, Elements);\r
- FwdDeclNode->replaceOperandWith(13, TParamsArray);\r
- } else\r
- FwdDeclNode->replaceOperandWith(10, Elements);\r
-\r
- RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDeclNode);\r
- return llvm::DIType(FwdDeclNode);\r
-}\r
-\r
-/// CreateType - get objective-c object type.\r
-llvm::DIType CGDebugInfo::CreateType(const ObjCObjectType *Ty,\r
- llvm::DIFile Unit) {\r
- // Ignore protocols.\r
- return getOrCreateType(Ty->getBaseType(), Unit);\r
-}\r
-\r
-/// CreateType - get objective-c interface type.\r
-llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,\r
- llvm::DIFile Unit) {\r
- ObjCInterfaceDecl *ID = Ty->getDecl();\r
- if (!ID)\r
- return llvm::DIType();\r
-\r
- // Get overall information about the record type for the debug info.\r
- llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation());\r
- unsigned Line = getLineNumber(ID->getLocation());\r
- unsigned RuntimeLang = TheCU.getLanguage();\r
-\r
- // If this is just a forward declaration return a special forward-declaration\r
- // debug type since we won't be able to lay out the entire type.\r
- ObjCInterfaceDecl *Def = ID->getDefinition();\r
- if (!Def) {\r
- llvm::DIType FwdDecl =\r
- DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,\r
- ID->getName(), TheCU, DefUnit, Line,\r
- RuntimeLang);\r
- return FwdDecl;\r
- }\r
-\r
- ID = Def;\r
-\r
- // Bit size, align and offset of the type.\r
- uint64_t Size = CGM.getContext().getTypeSize(Ty);\r
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);\r
-\r
- unsigned Flags = 0;\r
- if (ID->getImplementation())\r
- Flags |= llvm::DIDescriptor::FlagObjcClassComplete;\r
-\r
- llvm::DIType RealDecl =\r
- DBuilder.createStructType(Unit, ID->getName(), DefUnit,\r
- Line, Size, Align, Flags,\r
- llvm::DIArray(), RuntimeLang);\r
-\r
- // Otherwise, insert it into the CompletedTypeCache so that recursive uses\r
- // will find it and we're emitting the complete type.\r
- CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl;\r
- // Push the struct on region stack.\r
- llvm::TrackingVH<llvm::MDNode> FwdDeclNode(RealDecl);\r
-\r
- LexicalBlockStack.push_back(FwdDeclNode);\r
- RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);\r
-\r
- // Convert all the elements.\r
- SmallVector<llvm::Value *, 16> EltTys;\r
-\r
- ObjCInterfaceDecl *SClass = ID->getSuperClass();\r
- if (SClass) {\r
- llvm::DIType SClassTy =\r
- getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit);\r
- if (!SClassTy.isValid())\r
- return llvm::DIType();\r
- \r
- llvm::DIType InhTag =\r
- DBuilder.createInheritance(RealDecl, SClassTy, 0, 0);\r
- EltTys.push_back(InhTag);\r
- }\r
-\r
- for (ObjCContainerDecl::prop_iterator I = ID->prop_begin(),\r
- E = ID->prop_end(); I != E; ++I) {\r
- const ObjCPropertyDecl *PD = *I;\r
- SourceLocation Loc = PD->getLocation();\r
- llvm::DIFile PUnit = getOrCreateFile(Loc);\r
- unsigned PLine = getLineNumber(Loc);\r
- ObjCMethodDecl *Getter = PD->getGetterMethodDecl();\r
- ObjCMethodDecl *Setter = PD->getSetterMethodDecl();\r
- llvm::MDNode *PropertyNode =\r
- DBuilder.createObjCProperty(PD->getName(),\r
- PUnit, PLine,\r
- (Getter && Getter->isImplicit()) ? "" :\r
- getSelectorName(PD->getGetterName()),\r
- (Setter && Setter->isImplicit()) ? "" :\r
- getSelectorName(PD->getSetterName()),\r
- PD->getPropertyAttributes(),\r
- getOrCreateType(PD->getType(), PUnit));\r
- EltTys.push_back(PropertyNode);\r
- }\r
-\r
- const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID);\r
- unsigned FieldNo = 0;\r
- for (ObjCIvarDecl *Field = ID->all_declared_ivar_begin(); Field;\r
- Field = Field->getNextIvar(), ++FieldNo) {\r
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);\r
- if (!FieldTy.isValid())\r
- return llvm::DIType();\r
- \r
- StringRef FieldName = Field->getName();\r
-\r
- // Ignore unnamed fields.\r
- if (FieldName.empty())\r
- continue;\r
-\r
- // Get the location for the field.\r
- llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation());\r
- unsigned FieldLine = getLineNumber(Field->getLocation());\r
- QualType FType = Field->getType();\r
- uint64_t FieldSize = 0;\r
- unsigned FieldAlign = 0;\r
-\r
- if (!FType->isIncompleteArrayType()) {\r
-\r
- // Bit size, align and offset of the type.\r
- FieldSize = Field->isBitField()\r
- ? Field->getBitWidthValue(CGM.getContext())\r
- : CGM.getContext().getTypeSize(FType);\r
- FieldAlign = CGM.getContext().getTypeAlign(FType);\r
- }\r
-\r
- uint64_t FieldOffset;\r
- if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {\r
- // We don't know the runtime offset of an ivar if we're using the\r
- // non-fragile ABI. For bitfields, use the bit offset into the first\r
- // byte of storage of the bitfield. For other fields, use zero.\r
- if (Field->isBitField()) {\r
- FieldOffset = CGM.getObjCRuntime().ComputeBitfieldBitOffset(\r
- CGM, ID, Field);\r
- FieldOffset %= CGM.getContext().getCharWidth();\r
- } else {\r
- FieldOffset = 0;\r
- }\r
- } else {\r
- FieldOffset = RL.getFieldOffset(FieldNo);\r
- }\r
-\r
- unsigned Flags = 0;\r
- if (Field->getAccessControl() == ObjCIvarDecl::Protected)\r
- Flags = llvm::DIDescriptor::FlagProtected;\r
- else if (Field->getAccessControl() == ObjCIvarDecl::Private)\r
- Flags = llvm::DIDescriptor::FlagPrivate;\r
-\r
- llvm::MDNode *PropertyNode = NULL;\r
- if (ObjCImplementationDecl *ImpD = ID->getImplementation()) {\r
- if (ObjCPropertyImplDecl *PImpD = \r
- ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) {\r
- if (ObjCPropertyDecl *PD = PImpD->getPropertyDecl()) {\r
- SourceLocation Loc = PD->getLocation();\r
- llvm::DIFile PUnit = getOrCreateFile(Loc);\r
- unsigned PLine = getLineNumber(Loc);\r
- ObjCMethodDecl *Getter = PD->getGetterMethodDecl();\r
- ObjCMethodDecl *Setter = PD->getSetterMethodDecl();\r
- PropertyNode =\r
- DBuilder.createObjCProperty(PD->getName(),\r
- PUnit, PLine,\r
- (Getter && Getter->isImplicit()) ? "" :\r
- getSelectorName(PD->getGetterName()),\r
- (Setter && Setter->isImplicit()) ? "" :\r
- getSelectorName(PD->getSetterName()),\r
- PD->getPropertyAttributes(),\r
- getOrCreateType(PD->getType(), PUnit));\r
- }\r
- }\r
- }\r
- FieldTy = DBuilder.createObjCIVar(FieldName, FieldDefUnit,\r
- FieldLine, FieldSize, FieldAlign,\r
- FieldOffset, Flags, FieldTy,\r
- PropertyNode);\r
- EltTys.push_back(FieldTy);\r
- }\r
-\r
- llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);\r
- FwdDeclNode->replaceOperandWith(10, Elements);\r
- \r
- LexicalBlockStack.pop_back();\r
- return llvm::DIType(FwdDeclNode);\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, llvm::DIFile Unit) {\r
- llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit);\r
- int64_t Count = Ty->getNumElements();\r
- if (Count == 0)\r
- // If number of elements are not known then this is an unbounded array.\r
- // Use Count == -1 to express such arrays.\r
- Count = -1;\r
-\r
- llvm::Value *Subscript = DBuilder.getOrCreateSubrange(0, Count);\r
- llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);\r
-\r
- uint64_t Size = CGM.getContext().getTypeSize(Ty);\r
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);\r
-\r
- return DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,\r
- llvm::DIFile Unit) {\r
- uint64_t Size;\r
- uint64_t Align;\r
-\r
- // FIXME: make getTypeAlign() aware of VLAs and incomplete array types\r
- if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(Ty)) {\r
- Size = 0;\r
- Align =\r
- CGM.getContext().getTypeAlign(CGM.getContext().getBaseElementType(VAT));\r
- } else if (Ty->isIncompleteArrayType()) {\r
- Size = 0;\r
- if (Ty->getElementType()->isIncompleteType())\r
- Align = 0;\r
- else\r
- Align = CGM.getContext().getTypeAlign(Ty->getElementType());\r
- } else if (Ty->isDependentSizedArrayType() || Ty->isIncompleteType()) {\r
- Size = 0;\r
- Align = 0;\r
- } else {\r
- // Size and align of the whole array, not the element type.\r
- Size = CGM.getContext().getTypeSize(Ty);\r
- Align = CGM.getContext().getTypeAlign(Ty);\r
- }\r
-\r
- // Add the dimensions of the array. FIXME: This loses CV qualifiers from\r
- // interior arrays, do we care? Why aren't nested arrays represented the\r
- // obvious/recursive way?\r
- SmallVector<llvm::Value *, 8> Subscripts;\r
- QualType EltTy(Ty, 0);\r
- while ((Ty = dyn_cast<ArrayType>(EltTy))) {\r
- // If the number of elements is known, then count is that number. Otherwise,\r
- // it's -1. This allows us to represent a subrange with an array of 0\r
- // elements, like this:\r
- //\r
- // struct foo {\r
- // int x[0];\r
- // };\r
- int64_t Count = -1; // Count == -1 is an unbounded array.\r
- if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty))\r
- Count = CAT->getSize().getZExtValue();\r
- \r
- // FIXME: Verify this is right for VLAs.\r
- Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));\r
- EltTy = Ty->getElementType();\r
- }\r
-\r
- llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts);\r
-\r
- llvm::DIType DbgTy = \r
- DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit),\r
- SubscriptArray);\r
- return DbgTy;\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty, \r
- llvm::DIFile Unit) {\r
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type, \r
- Ty, Ty->getPointeeType(), Unit);\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty, \r
- llvm::DIFile Unit) {\r
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type, \r
- Ty, Ty->getPointeeType(), Unit);\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty, \r
- llvm::DIFile U) {\r
- QualType PointerDiffTy = CGM.getContext().getPointerDiffType();\r
- llvm::DIType PointerDiffDITy = getOrCreateType(PointerDiffTy, U);\r
- \r
- if (!Ty->getPointeeType()->isFunctionType()) {\r
- // We have a data member pointer type.\r
- return PointerDiffDITy;\r
- }\r
- \r
- // We have a member function pointer type. Treat it as a struct with two\r
- // ptrdiff_t members.\r
- std::pair<uint64_t, unsigned> Info = CGM.getContext().getTypeInfo(Ty);\r
-\r
- uint64_t FieldOffset = 0;\r
- llvm::Value *ElementTypes[2];\r
- \r
- // FIXME: This should be a DW_TAG_pointer_to_member type.\r
- ElementTypes[0] =\r
- DBuilder.createMemberType(U, "ptr", U, 0,\r
- Info.first, Info.second, FieldOffset, 0,\r
- PointerDiffDITy);\r
- FieldOffset += Info.first;\r
- \r
- ElementTypes[1] =\r
- DBuilder.createMemberType(U, "ptr", U, 0,\r
- Info.first, Info.second, FieldOffset, 0,\r
- PointerDiffDITy);\r
- \r
- llvm::DIArray Elements = DBuilder.getOrCreateArray(ElementTypes);\r
-\r
- return DBuilder.createStructType(U, StringRef("test"), \r
- U, 0, FieldOffset, \r
- 0, 0, Elements);\r
-}\r
-\r
-llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty, \r
- llvm::DIFile U) {\r
- // Ignore the atomic wrapping\r
- // FIXME: What is the correct representation?\r
- return getOrCreateType(Ty->getValueType(), U);\r
-}\r
-\r
-/// CreateEnumType - get enumeration type.\r
-llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {\r
- uint64_t Size = 0;\r
- uint64_t Align = 0;\r
- if (!ED->getTypeForDecl()->isIncompleteType()) {\r
- Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());\r
- Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());\r
- }\r
-\r
- // If this is just a forward declaration, construct an appropriately\r
- // marked node and just return it.\r
- if (!ED->getDefinition()) {\r
- llvm::DIDescriptor EDContext;\r
- EDContext = getContextDescriptor(cast<Decl>(ED->getDeclContext()));\r
- llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());\r
- unsigned Line = getLineNumber(ED->getLocation());\r
- StringRef EDName = ED->getName();\r
- return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_enumeration_type,\r
- EDName, EDContext, DefUnit, Line, 0,\r
- Size, Align);\r
- }\r
-\r
- // Create DIEnumerator elements for each enumerator.\r
- SmallVector<llvm::Value *, 16> Enumerators;\r
- ED = ED->getDefinition();\r
- for (EnumDecl::enumerator_iterator\r
- Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end();\r
- Enum != EnumEnd; ++Enum) {\r
- Enumerators.push_back(\r
- DBuilder.createEnumerator(Enum->getName(),\r
- Enum->getInitVal().getZExtValue()));\r
- }\r
-\r
- // Return a CompositeType for the enum itself.\r
- llvm::DIArray EltArray = DBuilder.getOrCreateArray(Enumerators);\r
-\r
- llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());\r
- unsigned Line = getLineNumber(ED->getLocation());\r
- llvm::DIDescriptor EnumContext = \r
- getContextDescriptor(cast<Decl>(ED->getDeclContext()));\r
- llvm::DIType ClassTy = ED->isScopedUsingClassTag() ?\r
- getOrCreateType(ED->getIntegerType(), DefUnit) : llvm::DIType();\r
- llvm::DIType DbgTy = \r
- DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line,\r
- Size, Align, EltArray,\r
- ClassTy);\r
- return DbgTy;\r
-}\r
-\r
-static QualType UnwrapTypeForDebugInfo(QualType T) {\r
- do {\r
- QualType LastT = T;\r
- switch (T->getTypeClass()) {\r
- default:\r
- return T;\r
- case Type::TemplateSpecialization:\r
- T = cast<TemplateSpecializationType>(T)->desugar();\r
- break;\r
- case Type::TypeOfExpr:\r
- T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType();\r
- break;\r
- case Type::TypeOf:\r
- T = cast<TypeOfType>(T)->getUnderlyingType();\r
- break;\r
- case Type::Decltype:\r
- T = cast<DecltypeType>(T)->getUnderlyingType();\r
- break;\r
- case Type::UnaryTransform:\r
- T = cast<UnaryTransformType>(T)->getUnderlyingType();\r
- break;\r
- case Type::Attributed:\r
- T = cast<AttributedType>(T)->getEquivalentType();\r
- break;\r
- case Type::Elaborated:\r
- T = cast<ElaboratedType>(T)->getNamedType();\r
- break;\r
- case Type::Paren:\r
- T = cast<ParenType>(T)->getInnerType();\r
- break;\r
- case Type::SubstTemplateTypeParm: {\r
- // We need to keep the qualifiers handy since getReplacementType()\r
- // will strip them away.\r
- unsigned Quals = T.getLocalFastQualifiers();\r
- T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();\r
- T.addFastQualifiers(Quals);\r
- }\r
- break;\r
- case Type::Auto:\r
- T = cast<AutoType>(T)->getDeducedType();\r
- break;\r
- }\r
- \r
- assert(T != LastT && "Type unwrapping failed to unwrap!");\r
- if (T == LastT)\r
- return T;\r
- } while (true);\r
-}\r
-\r
-/// getType - Get the type from the cache or return null type if it doesn't exist.\r
-llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) {\r
-\r
- // Unwrap the type as needed for debug information.\r
- Ty = UnwrapTypeForDebugInfo(Ty);\r
- \r
- // Check for existing entry.\r
- llvm::DenseMap<void *, llvm::WeakVH>::iterator it =\r
- TypeCache.find(Ty.getAsOpaquePtr());\r
- if (it != TypeCache.end()) {\r
- // Verify that the debug info still exists.\r
- if (llvm::Value *V = it->second)\r
- return llvm::DIType(cast<llvm::MDNode>(V));\r
- }\r
-\r
- return llvm::DIType();\r
-}\r
-\r
-/// getCompletedTypeOrNull - Get the type from the cache or return null if it\r
-/// doesn't exist.\r
-llvm::DIType CGDebugInfo::getCompletedTypeOrNull(QualType Ty) {\r
-\r
- // Unwrap the type as needed for debug information.\r
- Ty = UnwrapTypeForDebugInfo(Ty);\r
-\r
- // Check for existing entry.\r
- llvm::DenseMap<void *, llvm::WeakVH>::iterator it =\r
- CompletedTypeCache.find(Ty.getAsOpaquePtr());\r
- if (it != CompletedTypeCache.end()) {\r
- // Verify that the debug info still exists.\r
- if (llvm::Value *V = it->second)\r
- return llvm::DIType(cast<llvm::MDNode>(V));\r
- }\r
-\r
- return llvm::DIType();\r
-}\r
-\r
-\r
-/// getOrCreateType - Get the type from the cache or create a new\r
-/// one if necessary.\r
-llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {\r
- if (Ty.isNull())\r
- return llvm::DIType();\r
-\r
- // Unwrap the type as needed for debug information.\r
- Ty = UnwrapTypeForDebugInfo(Ty);\r
-\r
- llvm::DIType T = getCompletedTypeOrNull(Ty);\r
-\r
- if (T.Verify())\r
- return T;\r
-\r
- // Otherwise create the type.\r
- llvm::DIType Res = CreateTypeNode(Ty, Unit);\r
-\r
- llvm::DIType TC = getTypeOrNull(Ty);\r
- if (TC.Verify() && TC.isForwardDecl())\r
- ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(),\r
- static_cast<llvm::Value*>(TC)));\r
- \r
- // And update the type cache.\r
- TypeCache[Ty.getAsOpaquePtr()] = Res;\r
-\r
- if (!Res.isForwardDecl())\r
- CompletedTypeCache[Ty.getAsOpaquePtr()] = Res;\r
-\r
- return Res;\r
-}\r
-\r
-/// CreateTypeNode - Create a new debug type node.\r
-llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {\r
- // Handle qualifiers, which recursively handles what they refer to.\r
- if (Ty.hasLocalQualifiers())\r
- return CreateQualifiedType(Ty, Unit);\r
-\r
- const char *Diag = 0;\r
- \r
- // Work out details of type.\r
- switch (Ty->getTypeClass()) {\r
-#define TYPE(Class, Base)\r
-#define ABSTRACT_TYPE(Class, Base)\r
-#define NON_CANONICAL_TYPE(Class, Base)\r
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:\r
-#include "clang/AST/TypeNodes.def"\r
- llvm_unreachable("Dependent types cannot show up in debug information");\r
-\r
- case Type::ExtVector:\r
- case Type::Vector:\r
- return CreateType(cast<VectorType>(Ty), Unit);\r
- case Type::ObjCObjectPointer:\r
- return CreateType(cast<ObjCObjectPointerType>(Ty), Unit);\r
- case Type::ObjCObject:\r
- return CreateType(cast<ObjCObjectType>(Ty), Unit);\r
- case Type::ObjCInterface:\r
- return CreateType(cast<ObjCInterfaceType>(Ty), Unit);\r
- case Type::Builtin:\r
- return CreateType(cast<BuiltinType>(Ty));\r
- case Type::Complex:\r
- return CreateType(cast<ComplexType>(Ty));\r
- case Type::Pointer:\r
- return CreateType(cast<PointerType>(Ty), Unit);\r
- case Type::BlockPointer:\r
- return CreateType(cast<BlockPointerType>(Ty), Unit);\r
- case Type::Typedef:\r
- return CreateType(cast<TypedefType>(Ty), Unit);\r
- case Type::Record:\r
- return CreateType(cast<RecordType>(Ty));\r
- case Type::Enum:\r
- return CreateEnumType(cast<EnumType>(Ty)->getDecl());\r
- case Type::FunctionProto:\r
- case Type::FunctionNoProto:\r
- return CreateType(cast<FunctionType>(Ty), Unit);\r
- case Type::ConstantArray:\r
- case Type::VariableArray:\r
- case Type::IncompleteArray:\r
- return CreateType(cast<ArrayType>(Ty), Unit);\r
-\r
- case Type::LValueReference:\r
- return CreateType(cast<LValueReferenceType>(Ty), Unit);\r
- case Type::RValueReference:\r
- return CreateType(cast<RValueReferenceType>(Ty), Unit);\r
-\r
- case Type::MemberPointer:\r
- return CreateType(cast<MemberPointerType>(Ty), Unit);\r
-\r
- case Type::Atomic:\r
- return CreateType(cast<AtomicType>(Ty), Unit);\r
-\r
- case Type::Attributed:\r
- case Type::TemplateSpecialization:\r
- case Type::Elaborated:\r
- case Type::Paren:\r
- case Type::SubstTemplateTypeParm:\r
- case Type::TypeOfExpr:\r
- case Type::TypeOf:\r
- case Type::Decltype:\r
- case Type::UnaryTransform:\r
- case Type::Auto:\r
- llvm_unreachable("type should have been unwrapped!");\r
- }\r
- \r
- assert(Diag && "Fall through without a diagnostic?");\r
- unsigned DiagID = CGM.getDiags().getCustomDiagID(DiagnosticsEngine::Error,\r
- "debug information for %0 is not yet supported");\r
- CGM.getDiags().Report(DiagID)\r
- << Diag;\r
- return llvm::DIType();\r
-}\r
-\r
-/// getOrCreateLimitedType - Get the type from the cache or create a new\r
-/// limited type if necessary.\r
-llvm::DIType CGDebugInfo::getOrCreateLimitedType(QualType Ty,\r
- llvm::DIFile Unit) {\r
- if (Ty.isNull())\r
- return llvm::DIType();\r
-\r
- // Unwrap the type as needed for debug information.\r
- Ty = UnwrapTypeForDebugInfo(Ty);\r
-\r
- llvm::DIType T = getTypeOrNull(Ty);\r
-\r
- // We may have cached a forward decl when we could have created\r
- // a non-forward decl. Go ahead and create a non-forward decl\r
- // now.\r
- if (T.Verify() && !T.isForwardDecl()) return T;\r
-\r
- // Otherwise create the type.\r
- llvm::DIType Res = CreateLimitedTypeNode(Ty, Unit);\r
-\r
- if (T.Verify() && T.isForwardDecl())\r
- ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(),\r
- static_cast<llvm::Value*>(T)));\r
-\r
- // And update the type cache.\r
- TypeCache[Ty.getAsOpaquePtr()] = Res;\r
- return Res;\r
-}\r
-\r
-// TODO: Currently used for context chains when limiting debug info.\r
-llvm::DIType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {\r
- RecordDecl *RD = Ty->getDecl();\r
- \r
- // Get overall information about the record type for the debug info.\r
- llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());\r
- unsigned Line = getLineNumber(RD->getLocation());\r
- StringRef RDName = getClassName(RD);\r
-\r
- llvm::DIDescriptor RDContext;\r
- if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::LimitedDebugInfo)\r
- RDContext = createContextChain(cast<Decl>(RD->getDeclContext()));\r
- else\r
- RDContext = getContextDescriptor(cast<Decl>(RD->getDeclContext()));\r
-\r
- // If this is just a forward declaration, construct an appropriately\r
- // marked node and just return it.\r
- if (!RD->getDefinition())\r
- return createRecordFwdDecl(RD, RDContext);\r
-\r
- uint64_t Size = CGM.getContext().getTypeSize(Ty);\r
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);\r
- const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);\r
- llvm::TrackingVH<llvm::MDNode> RealDecl;\r
- \r
- if (RD->isUnion())\r
- RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,\r
- Size, Align, 0, llvm::DIArray());\r
- else if (RD->isClass()) {\r
- // FIXME: This could be a struct type giving a default visibility different\r
- // than C++ class type, but needs llvm metadata changes first.\r
- RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line,\r
- Size, Align, 0, 0, llvm::DIType(),\r
- llvm::DIArray(), llvm::DIType(),\r
- llvm::DIArray());\r
- } else\r
- RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line,\r
- Size, Align, 0, llvm::DIArray());\r
-\r
- RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);\r
- TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = llvm::DIType(RealDecl);\r
-\r
- if (CXXDecl) {\r
- // A class's primary base or the class itself contains the vtable.\r
- llvm::MDNode *ContainingType = NULL;\r
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);\r
- if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {\r
- // Seek non virtual primary base root.\r
- while (1) {\r
- const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);\r
- const CXXRecordDecl *PBT = BRL.getPrimaryBase();\r
- if (PBT && !BRL.isPrimaryBaseVirtual())\r
- PBase = PBT;\r
- else\r
- break;\r
- }\r
- ContainingType =\r
- getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit);\r
- }\r
- else if (CXXDecl->isDynamicClass())\r
- ContainingType = RealDecl;\r
-\r
- RealDecl->replaceOperandWith(12, ContainingType);\r
- }\r
- return llvm::DIType(RealDecl);\r
-}\r
-\r
-/// CreateLimitedTypeNode - Create a new debug type node, but only forward\r
-/// declare composite types that haven't been processed yet.\r
-llvm::DIType CGDebugInfo::CreateLimitedTypeNode(QualType Ty,llvm::DIFile Unit) {\r
-\r
- // Work out details of type.\r
- switch (Ty->getTypeClass()) {\r
-#define TYPE(Class, Base)\r
-#define ABSTRACT_TYPE(Class, Base)\r
-#define NON_CANONICAL_TYPE(Class, Base)\r
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:\r
- #include "clang/AST/TypeNodes.def"\r
- llvm_unreachable("Dependent types cannot show up in debug information");\r
-\r
- case Type::Record:\r
- return CreateLimitedType(cast<RecordType>(Ty));\r
- default:\r
- return CreateTypeNode(Ty, Unit);\r
- }\r
-}\r
-\r
-/// CreateMemberType - Create new member and increase Offset by FType's size.\r
-llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,\r
- StringRef Name,\r
- uint64_t *Offset) {\r
- llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);\r
- uint64_t FieldSize = CGM.getContext().getTypeSize(FType);\r
- unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);\r
- llvm::DIType Ty = DBuilder.createMemberType(Unit, Name, Unit, 0,\r
- FieldSize, FieldAlign,\r
- *Offset, 0, FieldTy);\r
- *Offset += FieldSize;\r
- return Ty;\r
-}\r
-\r
-/// getFunctionDeclaration - Return debug info descriptor to describe method\r
-/// declaration for the given method definition.\r
-llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) {\r
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);\r
- if (!FD) return llvm::DISubprogram();\r
-\r
- // Setup context.\r
- getContextDescriptor(cast<Decl>(D->getDeclContext()));\r
-\r
- llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator\r
- MI = SPCache.find(FD->getCanonicalDecl());\r
- if (MI != SPCache.end()) {\r
- llvm::Value *V = MI->second;\r
- llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(V));\r
- if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition())\r
- return SP;\r
- }\r
-\r
- for (FunctionDecl::redecl_iterator I = FD->redecls_begin(),\r
- E = FD->redecls_end(); I != E; ++I) {\r
- const FunctionDecl *NextFD = *I;\r
- llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator\r
- MI = SPCache.find(NextFD->getCanonicalDecl());\r
- if (MI != SPCache.end()) {\r
- llvm::Value *V = MI->second;\r
- llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(V));\r
- if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition())\r
- return SP;\r
- }\r
- }\r
- return llvm::DISubprogram();\r
-}\r
-\r
-// getOrCreateFunctionType - Construct DIType. If it is a c++ method, include\r
-// implicit parameter "this".\r
-llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl *D,\r
- QualType FnType,\r
- llvm::DIFile F) {\r
-\r
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))\r
- return getOrCreateMethodType(Method, F);\r
- if (const ObjCMethodDecl *OMethod = dyn_cast<ObjCMethodDecl>(D)) {\r
- // Add "self" and "_cmd"\r
- SmallVector<llvm::Value *, 16> Elts;\r
-\r
- // First element is always return type. For 'void' functions it is NULL.\r
- Elts.push_back(getOrCreateType(OMethod->getResultType(), F));\r
- // "self" pointer is always first argument.\r
- llvm::DIType SelfTy = getOrCreateType(OMethod->getSelfDecl()->getType(), F);\r
- Elts.push_back(DBuilder.createObjectPointerType(SelfTy));\r
- // "_cmd" pointer is always second argument.\r
- llvm::DIType CmdTy = getOrCreateType(OMethod->getCmdDecl()->getType(), F);\r
- Elts.push_back(DBuilder.createArtificialType(CmdTy));\r
- // Get rest of the arguments.\r
- for (ObjCMethodDecl::param_const_iterator PI = OMethod->param_begin(), \r
- PE = OMethod->param_end(); PI != PE; ++PI)\r
- Elts.push_back(getOrCreateType((*PI)->getType(), F));\r
-\r
- llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);\r
- return DBuilder.createSubroutineType(F, EltTypeArray);\r
- }\r
- return getOrCreateType(FnType, F);\r
-}\r
-\r
-/// EmitFunctionStart - Constructs the debug code for entering a function.\r
-void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,\r
- llvm::Function *Fn,\r
- CGBuilderTy &Builder) {\r
-\r
- StringRef Name;\r
- StringRef LinkageName;\r
-\r
- FnBeginRegionCount.push_back(LexicalBlockStack.size());\r
-\r
- const Decl *D = GD.getDecl();\r
- // Function may lack declaration in source code if it is created by Clang\r
- // CodeGen (examples: _GLOBAL__I_a, __cxx_global_array_dtor, thunk).\r
- bool HasDecl = (D != 0);\r
- // Use the location of the declaration.\r
- SourceLocation Loc;\r
- if (HasDecl)\r
- Loc = D->getLocation();\r
-\r
- unsigned Flags = 0;\r
- llvm::DIFile Unit = getOrCreateFile(Loc);\r
- llvm::DIDescriptor FDContext(Unit);\r
- llvm::DIArray TParamsArray;\r
- if (!HasDecl) {\r
- // Use llvm function name.\r
- Name = Fn->getName();\r
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {\r
- // If there is a DISubprogram for this function available then use it.\r
- llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator\r
- FI = SPCache.find(FD->getCanonicalDecl());\r
- if (FI != SPCache.end()) {\r
- llvm::Value *V = FI->second;\r
- llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(V));\r
- if (SP.isSubprogram() && llvm::DISubprogram(SP).isDefinition()) {\r
- llvm::MDNode *SPN = SP;\r
- LexicalBlockStack.push_back(SPN);\r
- RegionMap[D] = llvm::WeakVH(SP);\r
- return;\r
- }\r
- }\r
- Name = getFunctionName(FD);\r
- // Use mangled name as linkage name for c/c++ functions.\r
- if (FD->hasPrototype()) {\r
- LinkageName = CGM.getMangledName(GD);\r
- Flags |= llvm::DIDescriptor::FlagPrototyped;\r
- }\r
- if (LinkageName == Name ||\r
- CGM.getCodeGenOpts().getDebugInfo() <= CodeGenOptions::DebugLineTablesOnly)\r
- LinkageName = StringRef();\r
-\r
- if (CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {\r
- if (const NamespaceDecl *NSDecl =\r
- dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))\r
- FDContext = getOrCreateNameSpace(NSDecl);\r
- else if (const RecordDecl *RDecl =\r
- dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))\r
- FDContext = getContextDescriptor(cast<Decl>(RDecl->getDeclContext()));\r
-\r
- // Collect template parameters.\r
- TParamsArray = CollectFunctionTemplateParams(FD, Unit);\r
- }\r
- } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {\r
- Name = getObjCMethodName(OMD);\r
- Flags |= llvm::DIDescriptor::FlagPrototyped;\r
- } else {\r
- // Use llvm function name.\r
- Name = Fn->getName();\r
- Flags |= llvm::DIDescriptor::FlagPrototyped;\r
- }\r
- if (!Name.empty() && Name[0] == '\01')\r
- Name = Name.substr(1);\r
-\r
- unsigned LineNo = getLineNumber(Loc);\r
- if (!HasDecl || D->isImplicit())\r
- Flags |= llvm::DIDescriptor::FlagArtificial;\r
-\r
- llvm::DIType DIFnType;\r
- llvm::DISubprogram SPDecl;\r
- if (HasDecl &&\r
- CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {\r
- DIFnType = getOrCreateFunctionType(D, FnType, Unit);\r
- SPDecl = getFunctionDeclaration(D);\r
- } else {\r
- // Create fake but valid subroutine type. Otherwise\r
- // llvm::DISubprogram::Verify() would return false, and\r
- // subprogram DIE will miss DW_AT_decl_file and\r
- // DW_AT_decl_line fields.\r
- SmallVector<llvm::Value*, 16> Elts;\r
- llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);\r
- DIFnType = DBuilder.createSubroutineType(Unit, EltTypeArray);\r
- }\r
- llvm::DISubprogram SP;\r
- SP = DBuilder.createFunction(FDContext, Name, LinkageName, Unit,\r
- LineNo, DIFnType,\r
- Fn->hasInternalLinkage(), true/*definition*/,\r
- getLineNumber(CurLoc), Flags,\r
- CGM.getLangOpts().Optimize,\r
- Fn, TParamsArray, SPDecl);\r
-\r
- // Push function on region stack.\r
- llvm::MDNode *SPN = SP;\r
- LexicalBlockStack.push_back(SPN);\r
- if (HasDecl)\r
- RegionMap[D] = llvm::WeakVH(SP);\r
-}\r
-\r
-/// EmitLocation - Emit metadata to indicate a change in line/column\r
-/// information in the source file.\r
-void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {\r
- \r
- // Update our current location\r
- setLocation(Loc);\r
-\r
- if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;\r
-\r
- // Don't bother if things are the same as last time.\r
- SourceManager &SM = CGM.getContext().getSourceManager();\r
- if (CurLoc == PrevLoc ||\r
- SM.getExpansionLoc(CurLoc) == SM.getExpansionLoc(PrevLoc))\r
- // New Builder may not be in sync with CGDebugInfo.\r
- if (!Builder.getCurrentDebugLocation().isUnknown())\r
- return;\r
- \r
- // Update last state.\r
- PrevLoc = CurLoc;\r
-\r
- llvm::MDNode *Scope = LexicalBlockStack.back();\r
- Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(CurLoc),\r
- getColumnNumber(CurLoc),\r
- Scope));\r
-}\r
-\r
-/// CreateLexicalBlock - Creates a new lexical block node and pushes it on\r
-/// the stack.\r
-void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {\r
- llvm::DIDescriptor D =\r
- DBuilder.createLexicalBlock(LexicalBlockStack.empty() ?\r
- llvm::DIDescriptor() :\r
- llvm::DIDescriptor(LexicalBlockStack.back()),\r
- getOrCreateFile(CurLoc),\r
- getLineNumber(CurLoc),\r
- getColumnNumber(CurLoc));\r
- llvm::MDNode *DN = D;\r
- LexicalBlockStack.push_back(DN);\r
-}\r
-\r
-/// EmitLexicalBlockStart - Constructs the debug code for entering a declarative\r
-/// region - beginning of a DW_TAG_lexical_block.\r
-void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc) {\r
- // Set our current location.\r
- setLocation(Loc);\r
-\r
- // Create a new lexical block and push it on the stack.\r
- CreateLexicalBlock(Loc);\r
-\r
- // Emit a line table change for the current location inside the new scope.\r
- Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(Loc),\r
- getColumnNumber(Loc),\r
- LexicalBlockStack.back()));\r
-}\r
-\r
-/// EmitLexicalBlockEnd - Constructs the debug code for exiting a declarative\r
-/// region - end of a DW_TAG_lexical_block.\r
-void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc) {\r
- assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");\r
-\r
- // Provide an entry in the line table for the end of the block.\r
- EmitLocation(Builder, Loc);\r
-\r
- LexicalBlockStack.pop_back();\r
-}\r
-\r
-/// EmitFunctionEnd - Constructs the debug code for exiting a function.\r
-void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {\r
- assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");\r
- unsigned RCount = FnBeginRegionCount.back();\r
- assert(RCount <= LexicalBlockStack.size() && "Region stack mismatch");\r
-\r
- // Pop all regions for this function.\r
- while (LexicalBlockStack.size() != RCount)\r
- EmitLexicalBlockEnd(Builder, CurLoc);\r
- FnBeginRegionCount.pop_back();\r
-}\r
-\r
-// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref. \r
-// See BuildByRefType.\r
-llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,\r
- uint64_t *XOffset) {\r
-\r
- SmallVector<llvm::Value *, 5> EltTys;\r
- QualType FType;\r
- uint64_t FieldSize, FieldOffset;\r
- unsigned FieldAlign;\r
- \r
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());\r
- QualType Type = VD->getType(); \r
-\r
- FieldOffset = 0;\r
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);\r
- EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));\r
- EltTys.push_back(CreateMemberType(Unit, FType, "__forwarding", &FieldOffset));\r
- FType = CGM.getContext().IntTy;\r
- EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));\r
- EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset));\r
-\r
- bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type, VD);\r
- if (HasCopyAndDispose) {\r
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);\r
- EltTys.push_back(CreateMemberType(Unit, FType, "__copy_helper",\r
- &FieldOffset));\r
- EltTys.push_back(CreateMemberType(Unit, FType, "__destroy_helper",\r
- &FieldOffset));\r
- }\r
- bool HasByrefExtendedLayout;\r
- Qualifiers::ObjCLifetime Lifetime;\r
- if (CGM.getContext().getByrefLifetime(Type,\r
- Lifetime, HasByrefExtendedLayout)\r
- && HasByrefExtendedLayout)\r
- EltTys.push_back(CreateMemberType(Unit, FType,\r
- "__byref_variable_layout",\r
- &FieldOffset));\r
- \r
- CharUnits Align = CGM.getContext().getDeclAlign(VD);\r
- if (Align > CGM.getContext().toCharUnitsFromBits(\r
- CGM.getContext().getTargetInfo().getPointerAlign(0))) {\r
- CharUnits FieldOffsetInBytes \r
- = CGM.getContext().toCharUnitsFromBits(FieldOffset);\r
- CharUnits AlignedOffsetInBytes\r
- = FieldOffsetInBytes.RoundUpToAlignment(Align);\r
- CharUnits NumPaddingBytes\r
- = AlignedOffsetInBytes - FieldOffsetInBytes;\r
- \r
- if (NumPaddingBytes.isPositive()) {\r
- llvm::APInt pad(32, NumPaddingBytes.getQuantity());\r
- FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy,\r
- pad, ArrayType::Normal, 0);\r
- EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset));\r
- }\r
- }\r
- \r
- FType = Type;\r
- llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);\r
- FieldSize = CGM.getContext().getTypeSize(FType);\r
- FieldAlign = CGM.getContext().toBits(Align);\r
-\r
- *XOffset = FieldOffset; \r
- FieldTy = DBuilder.createMemberType(Unit, VD->getName(), Unit,\r
- 0, FieldSize, FieldAlign,\r
- FieldOffset, 0, FieldTy);\r
- EltTys.push_back(FieldTy);\r
- FieldOffset += FieldSize;\r
- \r
- llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);\r
- \r
- unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;\r
- \r
- return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,\r
- Elements);\r
-}\r
-\r
-/// EmitDeclare - Emit local variable declaration debug info.\r
-void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,\r
- llvm::Value *Storage, \r
- unsigned ArgNo, CGBuilderTy &Builder) {\r
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);\r
- assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");\r
-\r
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());\r
- llvm::DIType Ty;\r
- uint64_t XOffset = 0;\r
- if (VD->hasAttr<BlocksAttr>())\r
- Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);\r
- else \r
- Ty = getOrCreateType(VD->getType(), Unit);\r
-\r
- // If there is no debug info for this type then do not emit debug info\r
- // for this variable.\r
- if (!Ty)\r
- return;\r
-\r
- if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage)) {\r
- // If Storage is an aggregate returned as 'sret' then let debugger know\r
- // about this.\r
- if (Arg->hasStructRetAttr())\r
- Ty = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, Ty);\r
- else if (CXXRecordDecl *Record = VD->getType()->getAsCXXRecordDecl()) {\r
- // If an aggregate variable has non trivial destructor or non trivial copy\r
- // constructor than it is pass indirectly. Let debug info know about this\r
- // by using reference of the aggregate type as a argument type.\r
- if (Record->hasNonTrivialCopyConstructor() ||\r
- !Record->hasTrivialDestructor())\r
- Ty = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, Ty);\r
- }\r
- }\r
- \r
- // Get location information.\r
- unsigned Line = getLineNumber(VD->getLocation());\r
- unsigned Column = getColumnNumber(VD->getLocation());\r
- unsigned Flags = 0;\r
- if (VD->isImplicit())\r
- Flags |= llvm::DIDescriptor::FlagArtificial;\r
- // If this is the first argument and it is implicit then\r
- // give it an object pointer flag.\r
- // FIXME: There has to be a better way to do this, but for static\r
- // functions there won't be an implicit param at arg1 and\r
- // otherwise it is 'self' or 'this'.\r
- if (isa<ImplicitParamDecl>(VD) && ArgNo == 1)\r
- Flags |= llvm::DIDescriptor::FlagObjectPointer;\r
-\r
- llvm::MDNode *Scope = LexicalBlockStack.back();\r
-\r
- StringRef Name = VD->getName();\r
- if (!Name.empty()) {\r
- if (VD->hasAttr<BlocksAttr>()) {\r
- CharUnits offset = CharUnits::fromQuantity(32);\r
- SmallVector<llvm::Value *, 9> addr;\r
- llvm::Type *Int64Ty = CGM.Int64Ty;\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));\r
- // offset of __forwarding field\r
- offset = CGM.getContext().toCharUnitsFromBits(\r
- CGM.getContext().getTargetInfo().getPointerWidth(0));\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));\r
- // offset of x field\r
- offset = CGM.getContext().toCharUnitsFromBits(XOffset);\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));\r
-\r
- // Create the descriptor for the variable.\r
- llvm::DIVariable D =\r
- DBuilder.createComplexVariable(Tag, \r
- llvm::DIDescriptor(Scope),\r
- VD->getName(), Unit, Line, Ty,\r
- addr, ArgNo);\r
- \r
- // Insert an llvm.dbg.declare into the current block.\r
- llvm::Instruction *Call =\r
- DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());\r
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));\r
- return;\r
- } else if (isa<VariableArrayType>(VD->getType())) {\r
- // These are "complex" variables in that they need an op_deref.\r
- // Create the descriptor for the variable.\r
- llvm::Value *Addr = llvm::ConstantInt::get(CGM.Int64Ty,\r
- llvm::DIBuilder::OpDeref);\r
- llvm::DIVariable D =\r
- DBuilder.createComplexVariable(Tag,\r
- llvm::DIDescriptor(Scope),\r
- Name, Unit, Line, Ty,\r
- Addr, ArgNo);\r
-\r
- // Insert an llvm.dbg.declare into the current block.\r
- llvm::Instruction *Call =\r
- DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());\r
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));\r
- return;\r
- }\r
- \r
- // Create the descriptor for the variable.\r
- llvm::DIVariable D =\r
- DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope), \r
- Name, Unit, Line, Ty, \r
- CGM.getLangOpts().Optimize, Flags, ArgNo);\r
- \r
- // Insert an llvm.dbg.declare into the current block.\r
- llvm::Instruction *Call =\r
- DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());\r
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));\r
- return;\r
- }\r
- \r
- // If VD is an anonymous union then Storage represents value for\r
- // all union fields.\r
- if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) {\r
- const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());\r
- if (RD->isUnion()) {\r
- for (RecordDecl::field_iterator I = RD->field_begin(),\r
- E = RD->field_end();\r
- I != E; ++I) {\r
- FieldDecl *Field = *I;\r
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);\r
- StringRef FieldName = Field->getName();\r
- \r
- // Ignore unnamed fields. Do not ignore unnamed records.\r
- if (FieldName.empty() && !isa<RecordType>(Field->getType()))\r
- continue;\r
- \r
- // Use VarDecl's Tag, Scope and Line number.\r
- llvm::DIVariable D =\r
- DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),\r
- FieldName, Unit, Line, FieldTy, \r
- CGM.getLangOpts().Optimize, Flags,\r
- ArgNo);\r
- \r
- // Insert an llvm.dbg.declare into the current block.\r
- llvm::Instruction *Call =\r
- DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());\r
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));\r
- }\r
- }\r
- }\r
-}\r
-\r
-void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,\r
- llvm::Value *Storage,\r
- CGBuilderTy &Builder) {\r
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);\r
- EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder);\r
-}\r
-\r
-void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,\r
- llvm::Value *Storage,\r
- CGBuilderTy &Builder,\r
- const CGBlockInfo &blockInfo) {\r
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);\r
- assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");\r
- \r
- if (Builder.GetInsertBlock() == 0)\r
- return;\r
- \r
- bool isByRef = VD->hasAttr<BlocksAttr>();\r
- \r
- uint64_t XOffset = 0;\r
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());\r
- llvm::DIType Ty;\r
- if (isByRef)\r
- Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);\r
- else \r
- Ty = getOrCreateType(VD->getType(), Unit);\r
-\r
- // Self is passed along as an implicit non-arg variable in a\r
- // block. Mark it as the object pointer.\r
- if (isa<ImplicitParamDecl>(VD) && VD->getName() == "self")\r
- Ty = DBuilder.createObjectPointerType(Ty);\r
-\r
- // Get location information.\r
- unsigned Line = getLineNumber(VD->getLocation());\r
- unsigned Column = getColumnNumber(VD->getLocation());\r
-\r
- const llvm::DataLayout &target = CGM.getDataLayout();\r
-\r
- CharUnits offset = CharUnits::fromQuantity(\r
- target.getStructLayout(blockInfo.StructureType)\r
- ->getElementOffset(blockInfo.getCapture(VD).getIndex()));\r
-\r
- SmallVector<llvm::Value *, 9> addr;\r
- llvm::Type *Int64Ty = CGM.Int64Ty;\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));\r
- if (isByRef) {\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));\r
- // offset of __forwarding field\r
- offset = CGM.getContext()\r
- .toCharUnitsFromBits(target.getPointerSizeInBits(0));\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));\r
- // offset of x field\r
- offset = CGM.getContext().toCharUnitsFromBits(XOffset);\r
- addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));\r
- }\r
-\r
- // Create the descriptor for the variable.\r
- llvm::DIVariable D =\r
- DBuilder.createComplexVariable(llvm::dwarf::DW_TAG_auto_variable, \r
- llvm::DIDescriptor(LexicalBlockStack.back()),\r
- VD->getName(), Unit, Line, Ty, addr);\r
- // Insert an llvm.dbg.declare into the current block.\r
- llvm::Instruction *Call =\r
- DBuilder.insertDeclare(Storage, D, Builder.GetInsertPoint());\r
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column,\r
- LexicalBlockStack.back()));\r
-}\r
-\r
-/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument\r
-/// variable declaration.\r
-void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,\r
- unsigned ArgNo,\r
- CGBuilderTy &Builder) {\r
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);\r
- EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, ArgNo, Builder);\r
-}\r
-\r
-namespace {\r
- struct BlockLayoutChunk {\r
- uint64_t OffsetInBits;\r
- const BlockDecl::Capture *Capture;\r
- };\r
- bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) {\r
- return l.OffsetInBits < r.OffsetInBits;\r
- }\r
-}\r
-\r
-void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,\r
- llvm::Value *addr,\r
- CGBuilderTy &Builder) {\r
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);\r
- ASTContext &C = CGM.getContext();\r
- const BlockDecl *blockDecl = block.getBlockDecl();\r
-\r
- // Collect some general information about the block's location.\r
- SourceLocation loc = blockDecl->getCaretLocation();\r
- llvm::DIFile tunit = getOrCreateFile(loc);\r
- unsigned line = getLineNumber(loc);\r
- unsigned column = getColumnNumber(loc);\r
- \r
- // Build the debug-info type for the block literal.\r
- getContextDescriptor(cast<Decl>(blockDecl->getDeclContext()));\r
-\r
- const llvm::StructLayout *blockLayout =\r
- CGM.getDataLayout().getStructLayout(block.StructureType);\r
-\r
- SmallVector<llvm::Value*, 16> fields;\r
- fields.push_back(createFieldType("__isa", C.VoidPtrTy, 0, loc, AS_public,\r
- blockLayout->getElementOffsetInBits(0),\r
- tunit, tunit));\r
- fields.push_back(createFieldType("__flags", C.IntTy, 0, loc, AS_public,\r
- blockLayout->getElementOffsetInBits(1),\r
- tunit, tunit));\r
- fields.push_back(createFieldType("__reserved", C.IntTy, 0, loc, AS_public,\r
- blockLayout->getElementOffsetInBits(2),\r
- tunit, tunit));\r
- fields.push_back(createFieldType("__FuncPtr", C.VoidPtrTy, 0, loc, AS_public,\r
- blockLayout->getElementOffsetInBits(3),\r
- tunit, tunit));\r
- fields.push_back(createFieldType("__descriptor",\r
- C.getPointerType(block.NeedsCopyDispose ?\r
- C.getBlockDescriptorExtendedType() :\r
- C.getBlockDescriptorType()),\r
- 0, loc, AS_public,\r
- blockLayout->getElementOffsetInBits(4),\r
- tunit, tunit));\r
-\r
- // We want to sort the captures by offset, not because DWARF\r
- // requires this, but because we're paranoid about debuggers.\r
- SmallVector<BlockLayoutChunk, 8> chunks;\r
-\r
- // 'this' capture.\r
- if (blockDecl->capturesCXXThis()) {\r
- BlockLayoutChunk chunk;\r
- chunk.OffsetInBits =\r
- blockLayout->getElementOffsetInBits(block.CXXThisIndex);\r
- chunk.Capture = 0;\r
- chunks.push_back(chunk);\r
- }\r
-\r
- // Variable captures.\r
- for (BlockDecl::capture_const_iterator\r
- i = blockDecl->capture_begin(), e = blockDecl->capture_end();\r
- i != e; ++i) {\r
- const BlockDecl::Capture &capture = *i;\r
- const VarDecl *variable = capture.getVariable();\r
- const CGBlockInfo::Capture &captureInfo = block.getCapture(variable);\r
-\r
- // Ignore constant captures.\r
- if (captureInfo.isConstant())\r
- continue;\r
-\r
- BlockLayoutChunk chunk;\r
- chunk.OffsetInBits =\r
- blockLayout->getElementOffsetInBits(captureInfo.getIndex());\r
- chunk.Capture = &capture;\r
- chunks.push_back(chunk);\r
- }\r
-\r
- // Sort by offset.\r
- llvm::array_pod_sort(chunks.begin(), chunks.end());\r
-\r
- for (SmallVectorImpl<BlockLayoutChunk>::iterator\r
- i = chunks.begin(), e = chunks.end(); i != e; ++i) {\r
- uint64_t offsetInBits = i->OffsetInBits;\r
- const BlockDecl::Capture *capture = i->Capture;\r
-\r
- // If we have a null capture, this must be the C++ 'this' capture.\r
- if (!capture) {\r
- const CXXMethodDecl *method =\r
- cast<CXXMethodDecl>(blockDecl->getNonClosureContext());\r
- QualType type = method->getThisType(C);\r
-\r
- fields.push_back(createFieldType("this", type, 0, loc, AS_public,\r
- offsetInBits, tunit, tunit));\r
- continue;\r
- }\r
-\r
- const VarDecl *variable = capture->getVariable();\r
- StringRef name = variable->getName();\r
-\r
- llvm::DIType fieldType;\r
- if (capture->isByRef()) {\r
- std::pair<uint64_t,unsigned> ptrInfo = C.getTypeInfo(C.VoidPtrTy);\r
-\r
- // FIXME: this creates a second copy of this type!\r
- uint64_t xoffset;\r
- fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset);\r
- fieldType = DBuilder.createPointerType(fieldType, ptrInfo.first);\r
- fieldType = DBuilder.createMemberType(tunit, name, tunit, line,\r
- ptrInfo.first, ptrInfo.second,\r
- offsetInBits, 0, fieldType);\r
- } else {\r
- fieldType = createFieldType(name, variable->getType(), 0,\r
- loc, AS_public, offsetInBits, tunit, tunit);\r
- }\r
- fields.push_back(fieldType);\r
- }\r
-\r
- SmallString<36> typeName;\r
- llvm::raw_svector_ostream(typeName)\r
- << "__block_literal_" << CGM.getUniqueBlockCount();\r
-\r
- llvm::DIArray fieldsArray = DBuilder.getOrCreateArray(fields);\r
-\r
- llvm::DIType type =\r
- DBuilder.createStructType(tunit, typeName.str(), tunit, line,\r
- CGM.getContext().toBits(block.BlockSize),\r
- CGM.getContext().toBits(block.BlockAlign),\r
- 0, fieldsArray);\r
- type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);\r
-\r
- // Get overall information about the block.\r
- unsigned flags = llvm::DIDescriptor::FlagArtificial;\r
- llvm::MDNode *scope = LexicalBlockStack.back();\r
- StringRef name = ".block_descriptor";\r
-\r
- // Create the descriptor for the parameter.\r
- llvm::DIVariable debugVar =\r
- DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable,\r
- llvm::DIDescriptor(scope), \r
- name, tunit, line, type, \r
- CGM.getLangOpts().Optimize, flags,\r
- cast<llvm::Argument>(addr)->getArgNo() + 1);\r
- \r
- // Insert an llvm.dbg.value into the current block.\r
- llvm::Instruction *declare =\r
- DBuilder.insertDbgValueIntrinsic(addr, 0, debugVar,\r
- Builder.GetInsertBlock());\r
- declare->setDebugLoc(llvm::DebugLoc::get(line, column, scope));\r
-}\r
-\r
-/// EmitGlobalVariable - Emit information about a global variable.\r
-void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,\r
- const VarDecl *D) {\r
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);\r
- // Create global variable debug descriptor.\r
- llvm::DIFile Unit = getOrCreateFile(D->getLocation());\r
- unsigned LineNo = getLineNumber(D->getLocation());\r
-\r
- setLocation(D->getLocation());\r
-\r
- QualType T = D->getType();\r
- if (T->isIncompleteArrayType()) {\r
-\r
- // CodeGen turns int[] into int[1] so we'll do the same here.\r
- llvm::APInt ConstVal(32, 1);\r
- QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();\r
-\r
- T = CGM.getContext().getConstantArrayType(ET, ConstVal,\r
- ArrayType::Normal, 0);\r
- }\r
- StringRef DeclName = D->getName();\r
- StringRef LinkageName;\r
- if (D->getDeclContext() && !isa<FunctionDecl>(D->getDeclContext())\r
- && !isa<ObjCMethodDecl>(D->getDeclContext()))\r
- LinkageName = Var->getName();\r
- if (LinkageName == DeclName)\r
- LinkageName = StringRef();\r
- llvm::DIDescriptor DContext = \r
- getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));\r
- DBuilder.createStaticVariable(DContext, DeclName, LinkageName,\r
- Unit, LineNo, getOrCreateType(T, Unit),\r
- Var->hasInternalLinkage(), Var);\r
-}\r
-\r
-/// EmitGlobalVariable - Emit information about an objective-c interface.\r
-void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,\r
- ObjCInterfaceDecl *ID) {\r
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);\r
- // Create global variable debug descriptor.\r
- llvm::DIFile Unit = getOrCreateFile(ID->getLocation());\r
- unsigned LineNo = getLineNumber(ID->getLocation());\r
-\r
- StringRef Name = ID->getName();\r
-\r
- QualType T = CGM.getContext().getObjCInterfaceType(ID);\r
- if (T->isIncompleteArrayType()) {\r
-\r
- // CodeGen turns int[] into int[1] so we'll do the same here.\r
- llvm::APInt ConstVal(32, 1);\r
- QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();\r
-\r
- T = CGM.getContext().getConstantArrayType(ET, ConstVal,\r
- ArrayType::Normal, 0);\r
- }\r
-\r
- DBuilder.createGlobalVariable(Name, Unit, LineNo,\r
- getOrCreateType(T, Unit),\r
- Var->hasInternalLinkage(), Var);\r
-}\r
-\r
-/// EmitGlobalVariable - Emit global variable's debug info.\r
-void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, \r
- llvm::Constant *Init) {\r
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);\r
- // Create the descriptor for the variable.\r
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());\r
- StringRef Name = VD->getName();\r
- llvm::DIType Ty = getOrCreateType(VD->getType(), Unit);\r
- if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(VD)) {\r
- const EnumDecl *ED = cast<EnumDecl>(ECD->getDeclContext());\r
- assert(isa<EnumType>(ED->getTypeForDecl()) && "Enum without EnumType?");\r
- Ty = getOrCreateType(QualType(ED->getTypeForDecl(), 0), Unit);\r
- }\r
- // Do not use DIGlobalVariable for enums.\r
- if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)\r
- return;\r
- DBuilder.createStaticVariable(Unit, Name, Name, Unit,\r
- getLineNumber(VD->getLocation()),\r
- Ty, true, Init);\r
-}\r
-\r
-/// getOrCreateNamesSpace - Return namespace descriptor for the given\r
-/// namespace decl.\r
-llvm::DINameSpace \r
-CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {\r
- llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH>::iterator I = \r
- NameSpaceCache.find(NSDecl);\r
- if (I != NameSpaceCache.end())\r
- return llvm::DINameSpace(cast<llvm::MDNode>(I->second));\r
- \r
- unsigned LineNo = getLineNumber(NSDecl->getLocation());\r
- llvm::DIFile FileD = getOrCreateFile(NSDecl->getLocation());\r
- llvm::DIDescriptor Context = \r
- getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));\r
- llvm::DINameSpace NS =\r
- DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);\r
- NameSpaceCache[NSDecl] = llvm::WeakVH(NS);\r
- return NS;\r
-}\r
-\r
-void CGDebugInfo::finalize() {\r
- for (std::vector<std::pair<void *, llvm::WeakVH> >::const_iterator VI\r
- = ReplaceMap.begin(), VE = ReplaceMap.end(); VI != VE; ++VI) {\r
- llvm::DIType Ty, RepTy;\r
- // Verify that the debug info still exists.\r
- if (llvm::Value *V = VI->second)\r
- Ty = llvm::DIType(cast<llvm::MDNode>(V));\r
- \r
- llvm::DenseMap<void *, llvm::WeakVH>::iterator it =\r
- TypeCache.find(VI->first);\r
- if (it != TypeCache.end()) {\r
- // Verify that the debug info still exists.\r
- if (llvm::Value *V = it->second)\r
- RepTy = llvm::DIType(cast<llvm::MDNode>(V));\r
- }\r
- \r
- if (Ty.Verify() && Ty.isForwardDecl() && RepTy.Verify()) {\r
- Ty.replaceAllUsesWith(RepTy);\r
- }\r
- }\r
- DBuilder.finalize();\r
-}\r
+//===--- 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();
+}
-//===--- CGDebugInfo.h - DebugInfo for LLVM CodeGen -------------*- C++ -*-===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This is the source level debug info generator for llvm translation.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#ifndef CLANG_CODEGEN_CGDEBUGINFO_H\r
-#define CLANG_CODEGEN_CGDEBUGINFO_H\r
-\r
-#include "CGBuilder.h"\r
-#include "clang/AST/Expr.h"\r
-#include "clang/AST/Type.h"\r
-#include "clang/Basic/SourceLocation.h"\r
-#include "llvm/ADT/DenseMap.h"\r
-#include "llvm/DIBuilder.h"\r
-#include "llvm/DebugInfo.h"\r
-#include "llvm/Support/Allocator.h"\r
-#include "llvm/Support/ValueHandle.h"\r
-\r
-namespace llvm {\r
- class MDNode;\r
-}\r
-\r
-namespace clang {\r
- class CXXMethodDecl;\r
- class VarDecl;\r
- class ObjCInterfaceDecl;\r
- class ClassTemplateSpecializationDecl;\r
- class GlobalDecl;\r
-\r
-namespace CodeGen {\r
- class CodeGenModule;\r
- class CodeGenFunction;\r
- class CGBlockInfo;\r
-\r
-/// CGDebugInfo - This class gathers all debug information during compilation\r
-/// and is responsible for emitting to llvm globals or pass directly to\r
-/// the backend.\r
-class CGDebugInfo {\r
- CodeGenModule &CGM;\r
- llvm::DIBuilder DBuilder;\r
- llvm::DICompileUnit TheCU;\r
- SourceLocation CurLoc, PrevLoc;\r
- llvm::DIType VTablePtrType;\r
- llvm::DIType ClassTy;\r
- llvm::DIType ObjTy;\r
- llvm::DIType SelTy;\r
- llvm::DIType OCLImage1dDITy, OCLImage1dArrayDITy, OCLImage1dBufferDITy;\r
- llvm::DIType OCLImage2dDITy, OCLImage2dArrayDITy;\r
- llvm::DIType OCLImage3dDITy;\r
- \r
- /// TypeCache - Cache of previously constructed Types.\r
- llvm::DenseMap<void *, llvm::WeakVH> TypeCache;\r
-\r
- /// CompleteTypeCache - Cache of previously constructed complete RecordTypes.\r
- llvm::DenseMap<void *, llvm::WeakVH> CompletedTypeCache;\r
-\r
- /// ReplaceMap - Cache of forward declared types to RAUW at the end of\r
- /// compilation.\r
- std::vector<std::pair<void *, llvm::WeakVH> >ReplaceMap;\r
-\r
- bool BlockLiteralGenericSet;\r
- llvm::DIType BlockLiteralGeneric;\r
-\r
- // LexicalBlockStack - Keep track of our current nested lexical block.\r
- std::vector<llvm::TrackingVH<llvm::MDNode> > LexicalBlockStack;\r
- llvm::DenseMap<const Decl *, llvm::WeakVH> RegionMap;\r
- // FnBeginRegionCount - Keep track of LexicalBlockStack counter at the\r
- // beginning of a function. This is used to pop unbalanced regions at\r
- // the end of a function.\r
- std::vector<unsigned> FnBeginRegionCount;\r
-\r
- /// DebugInfoNames - This is a storage for names that are\r
- /// constructed on demand. For example, C++ destructors, C++ operators etc..\r
- llvm::BumpPtrAllocator DebugInfoNames;\r
- StringRef CWDName;\r
-\r
- llvm::DenseMap<const char *, llvm::WeakVH> DIFileCache;\r
- llvm::DenseMap<const FunctionDecl *, llvm::WeakVH> SPCache;\r
- llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH> NameSpaceCache;\r
-\r
- /// Helper functions for getOrCreateType.\r
- llvm::DIType CreateType(const BuiltinType *Ty);\r
- llvm::DIType CreateType(const ComplexType *Ty);\r
- llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile F);\r
- llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile F);\r
- llvm::DIType CreateType(const ObjCObjectPointerType *Ty,\r
- llvm::DIFile F);\r
- llvm::DIType CreateType(const PointerType *Ty, llvm::DIFile F);\r
- llvm::DIType CreateType(const BlockPointerType *Ty, llvm::DIFile F);\r
- llvm::DIType CreateType(const FunctionType *Ty, llvm::DIFile F);\r
- llvm::DIType CreateType(const RecordType *Ty);\r
- llvm::DIType CreateLimitedType(const RecordType *Ty);\r
- llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F);\r
- llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F);\r
- llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F);\r
- llvm::DIType CreateType(const ArrayType *Ty, llvm::DIFile F);\r
- llvm::DIType CreateType(const LValueReferenceType *Ty, llvm::DIFile F);\r
- llvm::DIType CreateType(const RValueReferenceType *Ty, llvm::DIFile Unit);\r
- llvm::DIType CreateType(const MemberPointerType *Ty, llvm::DIFile F);\r
- llvm::DIType CreateType(const AtomicType *Ty, llvm::DIFile F);\r
- llvm::DIType CreateEnumType(const EnumDecl *ED);\r
- llvm::DIType getTypeOrNull(const QualType);\r
- llvm::DIType getCompletedTypeOrNull(const QualType);\r
- llvm::DIType getOrCreateMethodType(const CXXMethodDecl *Method,\r
- llvm::DIFile F);\r
- llvm::DIType getOrCreateFunctionType(const Decl *D, QualType FnType,\r
- llvm::DIFile F);\r
- llvm::DIType getOrCreateVTablePtrType(llvm::DIFile F);\r
- llvm::DINameSpace getOrCreateNameSpace(const NamespaceDecl *N);\r
- llvm::DIType CreatePointeeType(QualType PointeeTy, llvm::DIFile F);\r
- llvm::DIType CreatePointerLikeType(unsigned Tag,\r
- const Type *Ty, QualType PointeeTy,\r
- llvm::DIFile F);\r
-\r
- llvm::DIType getOrCreateStructPtrType(StringRef Name, llvm::DIType &Cache);\r
-\r
- llvm::DISubprogram CreateCXXMemberFunction(const CXXMethodDecl *Method,\r
- llvm::DIFile F,\r
- llvm::DIType RecordTy);\r
- \r
- void CollectCXXMemberFunctions(const CXXRecordDecl *Decl,\r
- llvm::DIFile F,\r
- SmallVectorImpl<llvm::Value *> &E,\r
- llvm::DIType T);\r
-\r
- void CollectCXXFriends(const CXXRecordDecl *Decl,\r
- llvm::DIFile F,\r
- SmallVectorImpl<llvm::Value *> &EltTys,\r
- llvm::DIType RecordTy);\r
-\r
- void CollectCXXBases(const CXXRecordDecl *Decl,\r
- llvm::DIFile F,\r
- SmallVectorImpl<llvm::Value *> &EltTys,\r
- llvm::DIType RecordTy);\r
- \r
- llvm::DIArray\r
- CollectTemplateParams(const TemplateParameterList *TPList,\r
- const TemplateArgumentList &TAList,\r
- llvm::DIFile Unit);\r
- llvm::DIArray\r
- CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit);\r
- llvm::DIArray \r
- CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TS,\r
- llvm::DIFile F);\r
-\r
- llvm::DIType createFieldType(StringRef name, QualType type,\r
- uint64_t sizeInBitsOverride, SourceLocation loc,\r
- AccessSpecifier AS, uint64_t offsetInBits,\r
- llvm::DIFile tunit,\r
- llvm::DIDescriptor scope);\r
- void CollectRecordStaticVars(const RecordDecl *, llvm::DIType);\r
- void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F,\r
- SmallVectorImpl<llvm::Value *> &E,\r
- llvm::DIType RecordTy);\r
-\r
- void CollectVTableInfo(const CXXRecordDecl *Decl,\r
- llvm::DIFile F,\r
- SmallVectorImpl<llvm::Value *> &EltTys);\r
-\r
- // CreateLexicalBlock - Create a new lexical block node and push it on\r
- // the stack.\r
- void CreateLexicalBlock(SourceLocation Loc);\r
- \r
-public:\r
- CGDebugInfo(CodeGenModule &CGM);\r
- ~CGDebugInfo();\r
-\r
- void finalize();\r
-\r
- /// setLocation - Update the current source location. If \arg loc is\r
- /// invalid it is ignored.\r
- void setLocation(SourceLocation Loc);\r
-\r
- /// EmitLocation - Emit metadata to indicate a change in line/column\r
- /// information in the source file.\r
- void EmitLocation(CGBuilderTy &Builder, SourceLocation Loc);\r
-\r
- /// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate\r
- /// start of a new function.\r
- void EmitFunctionStart(GlobalDecl GD, QualType FnType,\r
- llvm::Function *Fn, CGBuilderTy &Builder);\r
-\r
- /// EmitFunctionEnd - Constructs the debug code for exiting a function.\r
- void EmitFunctionEnd(CGBuilderTy &Builder);\r
-\r
- /// EmitLexicalBlockStart - Emit metadata to indicate the beginning of a\r
- /// new lexical block and push the block onto the stack.\r
- void EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc);\r
-\r
- /// EmitLexicalBlockEnd - Emit metadata to indicate the end of a new lexical\r
- /// block and pop the current block.\r
- void EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc);\r
-\r
- /// EmitDeclareOfAutoVariable - Emit call to llvm.dbg.declare for an automatic\r
- /// variable declaration.\r
- void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI,\r
- CGBuilderTy &Builder);\r
-\r
- /// EmitDeclareOfBlockDeclRefVariable - Emit call to llvm.dbg.declare for an\r
- /// imported variable declaration in a block.\r
- void EmitDeclareOfBlockDeclRefVariable(const VarDecl *variable,\r
- llvm::Value *storage,\r
- CGBuilderTy &Builder,\r
- const CGBlockInfo &blockInfo);\r
-\r
- /// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument\r
- /// variable declaration.\r
- void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,\r
- unsigned ArgNo, CGBuilderTy &Builder);\r
-\r
- /// EmitDeclareOfBlockLiteralArgVariable - Emit call to\r
- /// llvm.dbg.declare for the block-literal argument to a block\r
- /// invocation function.\r
- void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,\r
- llvm::Value *addr,\r
- CGBuilderTy &Builder);\r
-\r
- /// EmitGlobalVariable - Emit information about a global variable.\r
- void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);\r
-\r
- /// EmitGlobalVariable - Emit information about an objective-c interface.\r
- void EmitGlobalVariable(llvm::GlobalVariable *GV, ObjCInterfaceDecl *Decl);\r
-\r
- /// EmitGlobalVariable - Emit global variable's debug info.\r
- void EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init);\r
-\r
- /// getOrCreateRecordType - Emit record type's standalone debug info. \r
- llvm::DIType getOrCreateRecordType(QualType Ty, SourceLocation L);\r
-\r
- /// getOrCreateInterfaceType - Emit an objective c interface type standalone\r
- /// debug info.\r
- llvm::DIType getOrCreateInterfaceType(QualType Ty,\r
- SourceLocation Loc);\r
-\r
-private:\r
- /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.\r
- void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,\r
- unsigned ArgNo, CGBuilderTy &Builder);\r
-\r
- // EmitTypeForVarWithBlocksAttr - Build up structure info for the byref. \r
- // See BuildByRefType.\r
- llvm::DIType EmitTypeForVarWithBlocksAttr(const VarDecl *VD,\r
- uint64_t *OffSet);\r
-\r
- /// getContextDescriptor - Get context info for the decl.\r
- llvm::DIDescriptor getContextDescriptor(const Decl *Decl);\r
-\r
- /// createRecordFwdDecl - Create a forward decl for a RecordType in a given\r
- /// context.\r
- llvm::DIType createRecordFwdDecl(const RecordDecl *, llvm::DIDescriptor);\r
- \r
- /// createContextChain - Create a set of decls for the context chain.\r
- llvm::DIDescriptor createContextChain(const Decl *Decl);\r
-\r
- /// getCurrentDirname - Return current directory name.\r
- StringRef getCurrentDirname();\r
-\r
- /// CreateCompileUnit - Create new compile unit.\r
- void CreateCompileUnit();\r
-\r
- /// getOrCreateFile - Get the file debug info descriptor for the input \r
- /// location.\r
- llvm::DIFile getOrCreateFile(SourceLocation Loc);\r
-\r
- /// getOrCreateMainFile - Get the file info for main compile unit.\r
- llvm::DIFile getOrCreateMainFile();\r
-\r
- /// getOrCreateType - Get the type from the cache or create a new type if\r
- /// necessary.\r
- llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile F);\r
-\r
- /// getOrCreateLimitedType - Get the type from the cache or create a new\r
- /// partial type if necessary.\r
- llvm::DIType getOrCreateLimitedType(QualType Ty, llvm::DIFile F);\r
-\r
- /// CreateTypeNode - Create type metadata for a source language type.\r
- llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F);\r
-\r
- /// CreateLimitedTypeNode - Create type metadata for a source language\r
- /// type, but only partial types for records.\r
- llvm::DIType CreateLimitedTypeNode(QualType Ty, llvm::DIFile F);\r
-\r
- /// CreateMemberType - Create new member and increase Offset by FType's size.\r
- llvm::DIType CreateMemberType(llvm::DIFile Unit, QualType FType,\r
- StringRef Name, uint64_t *Offset);\r
-\r
- /// getFunctionDeclaration - Return debug info descriptor to describe method\r
- /// declaration for the given method definition.\r
- llvm::DISubprogram getFunctionDeclaration(const Decl *D);\r
-\r
- /// getFunctionName - Get function name for the given FunctionDecl. If the\r
- /// name is constructred on demand (e.g. C++ destructor) then the name\r
- /// is stored on the side.\r
- StringRef getFunctionName(const FunctionDecl *FD);\r
-\r
- /// getObjCMethodName - Returns the unmangled name of an Objective-C method.\r
- /// This is the display name for the debugging info. \r
- StringRef getObjCMethodName(const ObjCMethodDecl *FD);\r
-\r
- /// getSelectorName - Return selector name. This is used for debugging\r
- /// info.\r
- StringRef getSelectorName(Selector S);\r
-\r
- /// getClassName - Get class name including template argument list.\r
- StringRef getClassName(const RecordDecl *RD);\r
-\r
- /// getVTableName - Get vtable name for the given Class.\r
- StringRef getVTableName(const CXXRecordDecl *Decl);\r
-\r
- /// getLineNumber - Get line number for the location. If location is invalid\r
- /// then use current location.\r
- unsigned getLineNumber(SourceLocation Loc);\r
-\r
- /// getColumnNumber - Get column number for the location. If location is \r
- /// invalid then use current location.\r
- unsigned getColumnNumber(SourceLocation Loc);\r
-};\r
-} // namespace CodeGen\r
-} // namespace clang\r
-\r
-\r
-#endif\r
+//===--- 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
-//===----- CGOpenCLRuntime.cpp - Interface to OpenCL Runtimes -------------===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This provides an abstract class for OpenCL code generation. Concrete\r
-// subclasses of this implement code generation for specific OpenCL\r
-// runtime libraries.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "CGOpenCLRuntime.h"\r
-#include "CodeGenFunction.h"\r
-#include "llvm/GlobalValue.h"\r
-#include "llvm/DerivedTypes.h"\r
-#include <assert.h>\r
-\r
-using namespace clang;\r
-using namespace CodeGen;\r
-\r
-CGOpenCLRuntime::~CGOpenCLRuntime() {}\r
-\r
-void CGOpenCLRuntime::EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,\r
- const VarDecl &D) {\r
- return CGF.EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);\r
-}\r
-\r
-llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {\r
- assert(T->isOpenCLSpecificType() &&\r
- "Not an OpenCL specific type!");\r
-\r
- switch (cast<BuiltinType>(T)->getKind()) {\r
- default: \r
- llvm_unreachable("Unexpected opencl builtin type!");\r
- return 0;\r
- case BuiltinType::OCLImage1d:\r
- return llvm::PointerType::get(llvm::StructType::create(\r
- CGM.getLLVMContext(), "opencl.image1d_t"), 0);\r
- case BuiltinType::OCLImage1dArray:\r
- return llvm::PointerType::get(llvm::StructType::create(\r
- CGM.getLLVMContext(), "opencl.image1d_array_t"), 0);\r
- case BuiltinType::OCLImage1dBuffer:\r
- return llvm::PointerType::get(llvm::StructType::create(\r
- CGM.getLLVMContext(), "opencl.image1d_buffer_t"), 0);\r
- case BuiltinType::OCLImage2d:\r
- return llvm::PointerType::get(llvm::StructType::create(\r
- CGM.getLLVMContext(), "opencl.image2d_t"), 0);\r
- case BuiltinType::OCLImage2dArray:\r
- return llvm::PointerType::get(llvm::StructType::create(\r
- CGM.getLLVMContext(), "opencl.image2d_array_t"), 0);\r
- case BuiltinType::OCLImage3d:\r
- return llvm::PointerType::get(llvm::StructType::create(\r
- CGM.getLLVMContext(), "opencl.image3d_t"), 0);\r
- }\r
-}\r
+//===----- 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);
+}
-//===----- CGOpenCLRuntime.h - Interface to OpenCL Runtimes -----*- C++ -*-===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This provides an abstract class for OpenCL code generation. Concrete\r
-// subclasses of this implement code generation for specific OpenCL\r
-// runtime libraries.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#ifndef CLANG_CODEGEN_OPENCLRUNTIME_H\r
-#define CLANG_CODEGEN_OPENCLRUNTIME_H\r
-\r
-#include "clang/AST/Type.h"\r
-#include "llvm/Type.h"\r
-#include "llvm/Value.h"\r
-\r
-namespace clang {\r
-\r
-class VarDecl;\r
-\r
-namespace CodeGen {\r
-\r
-class CodeGenFunction;\r
-class CodeGenModule;\r
-\r
-class CGOpenCLRuntime {\r
-protected:\r
- CodeGenModule &CGM;\r
-\r
-public:\r
- CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM) {}\r
- virtual ~CGOpenCLRuntime();\r
-\r
- /// Emit the IR required for a work-group-local variable declaration, and add\r
- /// an entry to CGF's LocalDeclMap for D. The base class does this using\r
- /// CodeGenFunction::EmitStaticVarDecl to emit an internal global for D.\r
- virtual void EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,\r
- const VarDecl &D);\r
-\r
- virtual llvm::Type *convertOpenCLSpecificType(const Type *T);\r
-};\r
-\r
-}\r
-}\r
-\r
-#endif\r
+//===----- 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
-//===--- CGCXXRTTI.cpp - Emit LLVM Code for C++ RTTI descriptors ----------===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This contains code dealing with C++ code generation of RTTI descriptors.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "CodeGenModule.h"\r
-#include "CGCXXABI.h"\r
-#include "CGObjCRuntime.h"\r
-#include "clang/AST/RecordLayout.h"\r
-#include "clang/AST/Type.h"\r
-#include "clang/Frontend/CodeGenOptions.h"\r
-\r
-using namespace clang;\r
-using namespace CodeGen;\r
-\r
-namespace {\r
-class RTTIBuilder {\r
- CodeGenModule &CGM; // Per-module state.\r
- llvm::LLVMContext &VMContext;\r
- \r
- /// Fields - The fields of the RTTI descriptor currently being built.\r
- SmallVector<llvm::Constant *, 16> Fields;\r
-\r
- /// GetAddrOfTypeName - Returns the mangled type name of the given type.\r
- llvm::GlobalVariable *\r
- GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage);\r
-\r
- /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI \r
- /// descriptor of the given type.\r
- llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);\r
- \r
- /// BuildVTablePointer - Build the vtable pointer for the given type.\r
- void BuildVTablePointer(const Type *Ty);\r
- \r
- /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single\r
- /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b.\r
- void BuildSIClassTypeInfo(const CXXRecordDecl *RD);\r
- \r
- /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for\r
- /// classes with bases that do not satisfy the abi::__si_class_type_info \r
- /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.\r
- void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);\r
- \r
- /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used\r
- /// for pointer types.\r
- void BuildPointerTypeInfo(QualType PointeeTy);\r
-\r
- /// BuildObjCObjectTypeInfo - Build the appropriate kind of\r
- /// type_info for an object type.\r
- void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);\r
- \r
- /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info \r
- /// struct, used for member pointer types.\r
- void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);\r
- \r
-public:\r
- RTTIBuilder(CodeGenModule &CGM) : CGM(CGM), \r
- VMContext(CGM.getModule().getContext()) { }\r
-\r
- // Pointer type info flags.\r
- enum {\r
- /// PTI_Const - Type has const qualifier.\r
- PTI_Const = 0x1,\r
- \r
- /// PTI_Volatile - Type has volatile qualifier.\r
- PTI_Volatile = 0x2,\r
- \r
- /// PTI_Restrict - Type has restrict qualifier.\r
- PTI_Restrict = 0x4,\r
- \r
- /// PTI_Incomplete - Type is incomplete.\r
- PTI_Incomplete = 0x8,\r
- \r
- /// PTI_ContainingClassIncomplete - Containing class is incomplete.\r
- /// (in pointer to member).\r
- PTI_ContainingClassIncomplete = 0x10\r
- };\r
- \r
- // VMI type info flags.\r
- enum {\r
- /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.\r
- VMI_NonDiamondRepeat = 0x1,\r
- \r
- /// VMI_DiamondShaped - Class is diamond shaped.\r
- VMI_DiamondShaped = 0x2\r
- };\r
- \r
- // Base class type info flags.\r
- enum {\r
- /// BCTI_Virtual - Base class is virtual.\r
- BCTI_Virtual = 0x1,\r
- \r
- /// BCTI_Public - Base class is public.\r
- BCTI_Public = 0x2\r
- };\r
- \r
- /// BuildTypeInfo - Build the RTTI type info struct for the given type.\r
- ///\r
- /// \param Force - true to force the creation of this RTTI value\r
- llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false);\r
-};\r
-}\r
-\r
-llvm::GlobalVariable *\r
-RTTIBuilder::GetAddrOfTypeName(QualType Ty, \r
- llvm::GlobalVariable::LinkageTypes Linkage) {\r
- SmallString<256> OutName;\r
- llvm::raw_svector_ostream Out(OutName);\r
- CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);\r
- Out.flush();\r
- StringRef Name = OutName.str();\r
-\r
- // We know that the mangled name of the type starts at index 4 of the\r
- // mangled name of the typename, so we can just index into it in order to\r
- // get the mangled name of the type.\r
- llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,\r
- Name.substr(4));\r
-\r
- llvm::GlobalVariable *GV = \r
- CGM.CreateOrReplaceCXXRuntimeVariable(Name, Init->getType(), Linkage);\r
-\r
- GV->setInitializer(Init);\r
-\r
- return GV;\r
-}\r
-\r
-llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {\r
- // Mangle the RTTI name.\r
- SmallString<256> OutName;\r
- llvm::raw_svector_ostream Out(OutName);\r
- CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);\r
- Out.flush();\r
- StringRef Name = OutName.str();\r
-\r
- // Look for an existing global.\r
- llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);\r
- \r
- if (!GV) {\r
- // Create a new global variable.\r
- GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,\r
- /*Constant=*/true,\r
- llvm::GlobalValue::ExternalLinkage, 0, Name);\r
- }\r
- \r
- return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);\r
-}\r
-\r
-/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type\r
-/// info for that type is defined in the standard library.\r
-static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {\r
- // Itanium C++ ABI 2.9.2:\r
- // Basic type information (e.g. for "int", "bool", etc.) will be kept in\r
- // the run-time support library. Specifically, the run-time support\r
- // library should contain type_info objects for the types X, X* and \r
- // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,\r
- // unsigned char, signed char, short, unsigned short, int, unsigned int,\r
- // long, unsigned long, long long, unsigned long long, float, double,\r
- // long double, char16_t, char32_t, and the IEEE 754r decimal and \r
- // half-precision floating point types.\r
- switch (Ty->getKind()) {\r
- case BuiltinType::Void:\r
- case BuiltinType::NullPtr:\r
- case BuiltinType::Bool:\r
- case BuiltinType::WChar_S:\r
- case BuiltinType::WChar_U:\r
- case BuiltinType::Char_U:\r
- case BuiltinType::Char_S:\r
- case BuiltinType::UChar:\r
- case BuiltinType::SChar:\r
- case BuiltinType::Short:\r
- case BuiltinType::UShort:\r
- case BuiltinType::Int:\r
- case BuiltinType::UInt:\r
- case BuiltinType::Long:\r
- case BuiltinType::ULong:\r
- case BuiltinType::LongLong:\r
- case BuiltinType::ULongLong:\r
- case BuiltinType::Half:\r
- case BuiltinType::Float:\r
- case BuiltinType::Double:\r
- case BuiltinType::LongDouble:\r
- case BuiltinType::Char16:\r
- case BuiltinType::Char32:\r
- case BuiltinType::Int128:\r
- case BuiltinType::UInt128:\r
- case BuiltinType::OCLImage1d:\r
- case BuiltinType::OCLImage1dArray:\r
- case BuiltinType::OCLImage1dBuffer:\r
- case BuiltinType::OCLImage2d:\r
- case BuiltinType::OCLImage2dArray:\r
- case BuiltinType::OCLImage3d:\r
- return true;\r
- \r
- case BuiltinType::Dependent:\r
-#define BUILTIN_TYPE(Id, SingletonId)\r
-#define PLACEHOLDER_TYPE(Id, SingletonId) \\r
- case BuiltinType::Id:\r
-#include "clang/AST/BuiltinTypes.def"\r
- llvm_unreachable("asking for RRTI for a placeholder type!");\r
- \r
- case BuiltinType::ObjCId:\r
- case BuiltinType::ObjCClass:\r
- case BuiltinType::ObjCSel:\r
- llvm_unreachable("FIXME: Objective-C types are unsupported!");\r
- }\r
-\r
- llvm_unreachable("Invalid BuiltinType Kind!");\r
-}\r
-\r
-static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {\r
- QualType PointeeTy = PointerTy->getPointeeType();\r
- const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);\r
- if (!BuiltinTy)\r
- return false;\r
- \r
- // Check the qualifiers.\r
- Qualifiers Quals = PointeeTy.getQualifiers();\r
- Quals.removeConst();\r
- \r
- if (!Quals.empty())\r
- return false;\r
- \r
- return TypeInfoIsInStandardLibrary(BuiltinTy);\r
-}\r
-\r
-/// IsStandardLibraryRTTIDescriptor - Returns whether the type\r
-/// information for the given type exists in the standard library.\r
-static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {\r
- // Type info for builtin types is defined in the standard library.\r
- if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))\r
- return TypeInfoIsInStandardLibrary(BuiltinTy);\r
- \r
- // Type info for some pointer types to builtin types is defined in the\r
- // standard library.\r
- if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))\r
- return TypeInfoIsInStandardLibrary(PointerTy);\r
-\r
- return false;\r
-}\r
-\r
-/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for\r
-/// the given type exists somewhere else, and that we should not emit the type\r
-/// information in this translation unit. Assumes that it is not a\r
-/// standard-library type.\r
-static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty) {\r
- ASTContext &Context = CGM.getContext();\r
-\r
- // If RTTI is disabled, don't consider key functions.\r
- if (!Context.getLangOpts().RTTI) return false;\r
-\r
- if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {\r
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());\r
- if (!RD->hasDefinition())\r
- return false;\r
-\r
- if (!RD->isDynamicClass())\r
- return false;\r
-\r
- return !CGM.getVTables().ShouldEmitVTableInThisTU(RD);\r
- }\r
- \r
- return false;\r
-}\r
-\r
-/// IsIncompleteClassType - Returns whether the given record type is incomplete.\r
-static bool IsIncompleteClassType(const RecordType *RecordTy) {\r
- return !RecordTy->getDecl()->isCompleteDefinition();\r
-} \r
-\r
-/// ContainsIncompleteClassType - Returns whether the given type contains an\r
-/// incomplete class type. This is true if\r
-///\r
-/// * The given type is an incomplete class type.\r
-/// * The given type is a pointer type whose pointee type contains an \r
-/// incomplete class type.\r
-/// * The given type is a member pointer type whose class is an incomplete\r
-/// class type.\r
-/// * The given type is a member pointer type whoise pointee type contains an\r
-/// incomplete class type.\r
-/// is an indirect or direct pointer to an incomplete class type.\r
-static bool ContainsIncompleteClassType(QualType Ty) {\r
- if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {\r
- if (IsIncompleteClassType(RecordTy))\r
- return true;\r
- }\r
- \r
- if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))\r
- return ContainsIncompleteClassType(PointerTy->getPointeeType());\r
- \r
- if (const MemberPointerType *MemberPointerTy = \r
- dyn_cast<MemberPointerType>(Ty)) {\r
- // Check if the class type is incomplete.\r
- const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());\r
- if (IsIncompleteClassType(ClassType))\r
- return true;\r
- \r
- return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());\r
- }\r
- \r
- return false;\r
-}\r
-\r
-/// getTypeInfoLinkage - Return the linkage that the type info and type info\r
-/// name constants should have for the given type.\r
-static llvm::GlobalVariable::LinkageTypes \r
-getTypeInfoLinkage(CodeGenModule &CGM, QualType Ty) {\r
- // Itanium C++ ABI 2.9.5p7:\r
- // In addition, it and all of the intermediate abi::__pointer_type_info \r
- // structs in the chain down to the abi::__class_type_info for the\r
- // incomplete class type must be prevented from resolving to the \r
- // corresponding type_info structs for the complete class type, possibly\r
- // by making them local static objects. Finally, a dummy class RTTI is\r
- // generated for the incomplete type that will not resolve to the final \r
- // complete class RTTI (because the latter need not exist), possibly by \r
- // making it a local static object.\r
- if (ContainsIncompleteClassType(Ty))\r
- return llvm::GlobalValue::InternalLinkage;\r
- \r
- switch (Ty->getLinkage()) {\r
- case NoLinkage:\r
- case InternalLinkage:\r
- case UniqueExternalLinkage:\r
- return llvm::GlobalValue::InternalLinkage;\r
-\r
- case ExternalLinkage:\r
- if (!CGM.getLangOpts().RTTI) {\r
- // RTTI is not enabled, which means that this type info struct is going\r
- // to be used for exception handling. Give it linkonce_odr linkage.\r
- return llvm::GlobalValue::LinkOnceODRLinkage;\r
- }\r
-\r
- if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {\r
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());\r
- if (RD->hasAttr<WeakAttr>())\r
- return llvm::GlobalValue::WeakODRLinkage;\r
- if (RD->isDynamicClass())\r
- return CGM.getVTableLinkage(RD);\r
- }\r
-\r
- return llvm::GlobalValue::LinkOnceODRLinkage;\r
- }\r
-\r
- llvm_unreachable("Invalid linkage!");\r
-}\r
-\r
-// CanUseSingleInheritance - Return whether the given record decl has a "single, \r
-// public, non-virtual base at offset zero (i.e. the derived class is dynamic \r
-// iff the base is)", according to Itanium C++ ABI, 2.95p6b.\r
-static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {\r
- // Check the number of bases.\r
- if (RD->getNumBases() != 1)\r
- return false;\r
- \r
- // Get the base.\r
- CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();\r
- \r
- // Check that the base is not virtual.\r
- if (Base->isVirtual())\r
- return false;\r
- \r
- // Check that the base is public.\r
- if (Base->getAccessSpecifier() != AS_public)\r
- return false;\r
- \r
- // Check that the class is dynamic iff the base is.\r
- const CXXRecordDecl *BaseDecl = \r
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());\r
- if (!BaseDecl->isEmpty() && \r
- BaseDecl->isDynamicClass() != RD->isDynamicClass())\r
- return false;\r
- \r
- return true;\r
-}\r
-\r
-void RTTIBuilder::BuildVTablePointer(const Type *Ty) {\r
- // abi::__class_type_info.\r
- static const char * const ClassTypeInfo =\r
- "_ZTVN10__cxxabiv117__class_type_infoE";\r
- // abi::__si_class_type_info.\r
- static const char * const SIClassTypeInfo =\r
- "_ZTVN10__cxxabiv120__si_class_type_infoE";\r
- // abi::__vmi_class_type_info.\r
- static const char * const VMIClassTypeInfo =\r
- "_ZTVN10__cxxabiv121__vmi_class_type_infoE";\r
-\r
- const char *VTableName = 0;\r
-\r
- switch (Ty->getTypeClass()) {\r
-#define TYPE(Class, Base)\r
-#define ABSTRACT_TYPE(Class, Base)\r
-#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:\r
-#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:\r
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:\r
-#include "clang/AST/TypeNodes.def"\r
- llvm_unreachable("Non-canonical and dependent types shouldn't get here");\r
-\r
- case Type::LValueReference:\r
- case Type::RValueReference:\r
- llvm_unreachable("References shouldn't get here");\r
-\r
- case Type::Builtin:\r
- // GCC treats vector and complex types as fundamental types.\r
- case Type::Vector:\r
- case Type::ExtVector:\r
- case Type::Complex:\r
- case Type::Atomic:\r
- // FIXME: GCC treats block pointers as fundamental types?!\r
- case Type::BlockPointer:\r
- // abi::__fundamental_type_info.\r
- VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";\r
- break;\r
-\r
- case Type::ConstantArray:\r
- case Type::IncompleteArray:\r
- case Type::VariableArray:\r
- // abi::__array_type_info.\r
- VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";\r
- break;\r
-\r
- case Type::FunctionNoProto:\r
- case Type::FunctionProto:\r
- // abi::__function_type_info.\r
- VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";\r
- break;\r
-\r
- case Type::Enum:\r
- // abi::__enum_type_info.\r
- VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";\r
- break;\r
-\r
- case Type::Record: {\r
- const CXXRecordDecl *RD = \r
- cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());\r
- \r
- if (!RD->hasDefinition() || !RD->getNumBases()) {\r
- VTableName = ClassTypeInfo;\r
- } else if (CanUseSingleInheritance(RD)) {\r
- VTableName = SIClassTypeInfo;\r
- } else {\r
- VTableName = VMIClassTypeInfo;\r
- }\r
- \r
- break;\r
- }\r
-\r
- case Type::ObjCObject:\r
- // Ignore protocol qualifiers.\r
- Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();\r
-\r
- // Handle id and Class.\r
- if (isa<BuiltinType>(Ty)) {\r
- VTableName = ClassTypeInfo;\r
- break;\r
- }\r
-\r
- assert(isa<ObjCInterfaceType>(Ty));\r
- // Fall through.\r
-\r
- case Type::ObjCInterface:\r
- if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {\r
- VTableName = SIClassTypeInfo;\r
- } else {\r
- VTableName = ClassTypeInfo;\r
- }\r
- break;\r
-\r
- case Type::ObjCObjectPointer:\r
- case Type::Pointer:\r
- // abi::__pointer_type_info.\r
- VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";\r
- break;\r
-\r
- case Type::MemberPointer:\r
- // abi::__pointer_to_member_type_info.\r
- VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";\r
- break;\r
- }\r
-\r
- llvm::Constant *VTable = \r
- CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy);\r
- \r
- llvm::Type *PtrDiffTy = \r
- CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());\r
-\r
- // The vtable address point is 2.\r
- llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);\r
- VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Two);\r
- VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);\r
-\r
- Fields.push_back(VTable);\r
-}\r
-\r
-// maybeUpdateRTTILinkage - Will update the linkage of the RTTI data structures\r
-// from available_externally to the correct linkage if necessary. An example of\r
-// this is:\r
-//\r
-// struct A {\r
-// virtual void f();\r
-// };\r
-//\r
-// const std::type_info &g() {\r
-// return typeid(A);\r
-// }\r
-//\r
-// void A::f() { }\r
-//\r
-// When we're generating the typeid(A) expression, we do not yet know that\r
-// A's key function is defined in this translation unit, so we will give the\r
-// typeinfo and typename structures available_externally linkage. When A::f\r
-// forces the vtable to be generated, we need to change the linkage of the\r
-// typeinfo and typename structs, otherwise we'll end up with undefined\r
-// externals when linking.\r
-static void \r
-maybeUpdateRTTILinkage(CodeGenModule &CGM, llvm::GlobalVariable *GV,\r
- QualType Ty) {\r
- // We're only interested in globals with available_externally linkage.\r
- if (!GV->hasAvailableExternallyLinkage())\r
- return;\r
-\r
- // Get the real linkage for the type.\r
- llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty);\r
-\r
- // If variable is supposed to have available_externally linkage, we don't\r
- // need to do anything.\r
- if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)\r
- return;\r
-\r
- // Update the typeinfo linkage.\r
- GV->setLinkage(Linkage);\r
-\r
- // Get the typename global.\r
- SmallString<256> OutName;\r
- llvm::raw_svector_ostream Out(OutName);\r
- CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);\r
- Out.flush();\r
- StringRef Name = OutName.str();\r
-\r
- llvm::GlobalVariable *TypeNameGV = CGM.getModule().getNamedGlobal(Name);\r
-\r
- assert(TypeNameGV->hasAvailableExternallyLinkage() &&\r
- "Type name has different linkage from type info!");\r
-\r
- // And update its linkage.\r
- TypeNameGV->setLinkage(Linkage);\r
-}\r
-\r
-llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {\r
- // We want to operate on the canonical type.\r
- Ty = CGM.getContext().getCanonicalType(Ty);\r
-\r
- // Check if we've already emitted an RTTI descriptor for this type.\r
- SmallString<256> OutName;\r
- llvm::raw_svector_ostream Out(OutName);\r
- CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);\r
- Out.flush();\r
- StringRef Name = OutName.str();\r
-\r
- llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);\r
- if (OldGV && !OldGV->isDeclaration()) {\r
- maybeUpdateRTTILinkage(CGM, OldGV, Ty);\r
-\r
- return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy);\r
- }\r
-\r
- // Check if there is already an external RTTI descriptor for this type.\r
- bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);\r
- if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty)))\r
- return GetAddrOfExternalRTTIDescriptor(Ty);\r
-\r
- // Emit the standard library with external linkage.\r
- llvm::GlobalVariable::LinkageTypes Linkage;\r
- if (IsStdLib)\r
- Linkage = llvm::GlobalValue::ExternalLinkage;\r
- else\r
- Linkage = getTypeInfoLinkage(CGM, Ty);\r
-\r
- // Add the vtable pointer.\r
- BuildVTablePointer(cast<Type>(Ty));\r
- \r
- // And the name.\r
- llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);\r
-\r
- Fields.push_back(llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy));\r
-\r
- switch (Ty->getTypeClass()) {\r
-#define TYPE(Class, Base)\r
-#define ABSTRACT_TYPE(Class, Base)\r
-#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:\r
-#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:\r
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:\r
-#include "clang/AST/TypeNodes.def"\r
- llvm_unreachable("Non-canonical and dependent types shouldn't get here");\r
-\r
- // GCC treats vector types as fundamental types.\r
- case Type::Builtin:\r
- case Type::Vector:\r
- case Type::ExtVector:\r
- case Type::Complex:\r
- case Type::BlockPointer:\r
- // Itanium C++ ABI 2.9.5p4:\r
- // abi::__fundamental_type_info adds no data members to std::type_info.\r
- break;\r
-\r
- case Type::LValueReference:\r
- case Type::RValueReference:\r
- llvm_unreachable("References shouldn't get here");\r
-\r
- case Type::ConstantArray:\r
- case Type::IncompleteArray:\r
- case Type::VariableArray:\r
- // Itanium C++ ABI 2.9.5p5:\r
- // abi::__array_type_info adds no data members to std::type_info.\r
- break;\r
-\r
- case Type::FunctionNoProto:\r
- case Type::FunctionProto:\r
- // Itanium C++ ABI 2.9.5p5:\r
- // abi::__function_type_info adds no data members to std::type_info.\r
- break;\r
-\r
- case Type::Enum:\r
- // Itanium C++ ABI 2.9.5p5:\r
- // abi::__enum_type_info adds no data members to std::type_info.\r
- break;\r
-\r
- case Type::Record: {\r
- const CXXRecordDecl *RD = \r
- cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());\r
- if (!RD->hasDefinition() || !RD->getNumBases()) {\r
- // We don't need to emit any fields.\r
- break;\r
- }\r
- \r
- if (CanUseSingleInheritance(RD))\r
- BuildSIClassTypeInfo(RD);\r
- else \r
- BuildVMIClassTypeInfo(RD);\r
-\r
- break;\r
- }\r
-\r
- case Type::ObjCObject:\r
- case Type::ObjCInterface:\r
- BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));\r
- break;\r
-\r
- case Type::ObjCObjectPointer:\r
- BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());\r
- break; \r
- \r
- case Type::Pointer:\r
- BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());\r
- break;\r
-\r
- case Type::MemberPointer:\r
- BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));\r
- break;\r
-\r
- case Type::Atomic:\r
- // No fields, at least for the moment.\r
- break;\r
- }\r
-\r
- llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);\r
-\r
- llvm::GlobalVariable *GV = \r
- new llvm::GlobalVariable(CGM.getModule(), Init->getType(), \r
- /*Constant=*/true, Linkage, Init, Name);\r
- \r
- // If there's already an old global variable, replace it with the new one.\r
- if (OldGV) {\r
- GV->takeName(OldGV);\r
- llvm::Constant *NewPtr = \r
- llvm::ConstantExpr::getBitCast(GV, OldGV->getType());\r
- OldGV->replaceAllUsesWith(NewPtr);\r
- OldGV->eraseFromParent();\r
- }\r
-\r
- // GCC only relies on the uniqueness of the type names, not the\r
- // type_infos themselves, so we can emit these as hidden symbols.\r
- // But don't do this if we're worried about strict visibility\r
- // compatibility.\r
- if (const RecordType *RT = dyn_cast<RecordType>(Ty)) {\r
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());\r
-\r
- CGM.setTypeVisibility(GV, RD, CodeGenModule::TVK_ForRTTI);\r
- CGM.setTypeVisibility(TypeName, RD, CodeGenModule::TVK_ForRTTIName);\r
- } else {\r
- Visibility TypeInfoVisibility = DefaultVisibility;\r
- if (CGM.getCodeGenOpts().HiddenWeakVTables &&\r
- Linkage == llvm::GlobalValue::LinkOnceODRLinkage)\r
- TypeInfoVisibility = HiddenVisibility;\r
-\r
- // The type name should have the same visibility as the type itself.\r
- Visibility ExplicitVisibility = Ty->getVisibility();\r
- TypeName->setVisibility(CodeGenModule::\r
- GetLLVMVisibility(ExplicitVisibility));\r
- \r
- TypeInfoVisibility = minVisibility(TypeInfoVisibility, Ty->getVisibility());\r
- GV->setVisibility(CodeGenModule::GetLLVMVisibility(TypeInfoVisibility));\r
- }\r
-\r
- GV->setUnnamedAddr(true);\r
-\r
- return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);\r
-}\r
-\r
-/// ComputeQualifierFlags - Compute the pointer type info flags from the\r
-/// given qualifier.\r
-static unsigned ComputeQualifierFlags(Qualifiers Quals) {\r
- unsigned Flags = 0;\r
-\r
- if (Quals.hasConst())\r
- Flags |= RTTIBuilder::PTI_Const;\r
- if (Quals.hasVolatile())\r
- Flags |= RTTIBuilder::PTI_Volatile;\r
- if (Quals.hasRestrict())\r
- Flags |= RTTIBuilder::PTI_Restrict;\r
-\r
- return Flags;\r
-}\r
-\r
-/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info\r
-/// for the given Objective-C object type.\r
-void RTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {\r
- // Drop qualifiers.\r
- const Type *T = OT->getBaseType().getTypePtr();\r
- assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));\r
-\r
- // The builtin types are abi::__class_type_infos and don't require\r
- // extra fields.\r
- if (isa<BuiltinType>(T)) return;\r
-\r
- ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl();\r
- ObjCInterfaceDecl *Super = Class->getSuperClass();\r
-\r
- // Root classes are also __class_type_info.\r
- if (!Super) return;\r
-\r
- QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);\r
-\r
- // Everything else is single inheritance.\r
- llvm::Constant *BaseTypeInfo = RTTIBuilder(CGM).BuildTypeInfo(SuperTy);\r
- Fields.push_back(BaseTypeInfo);\r
-}\r
-\r
-/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single\r
-/// inheritance, according to the Itanium C++ ABI, 2.95p6b.\r
-void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {\r
- // Itanium C++ ABI 2.9.5p6b:\r
- // It adds to abi::__class_type_info a single member pointing to the \r
- // type_info structure for the base type,\r
- llvm::Constant *BaseTypeInfo = \r
- RTTIBuilder(CGM).BuildTypeInfo(RD->bases_begin()->getType());\r
- Fields.push_back(BaseTypeInfo);\r
-}\r
-\r
-namespace {\r
- /// SeenBases - Contains virtual and non-virtual bases seen when traversing\r
- /// a class hierarchy.\r
- struct SeenBases {\r
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;\r
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;\r
- };\r
-}\r
-\r
-/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in\r
-/// abi::__vmi_class_type_info.\r
-///\r
-static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base, \r
- SeenBases &Bases) {\r
- \r
- unsigned Flags = 0;\r
- \r
- const CXXRecordDecl *BaseDecl = \r
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());\r
- \r
- if (Base->isVirtual()) {\r
- // Mark the virtual base as seen.\r
- if (!Bases.VirtualBases.insert(BaseDecl)) {\r
- // If this virtual base has been seen before, then the class is diamond\r
- // shaped.\r
- Flags |= RTTIBuilder::VMI_DiamondShaped;\r
- } else {\r
- if (Bases.NonVirtualBases.count(BaseDecl))\r
- Flags |= RTTIBuilder::VMI_NonDiamondRepeat;\r
- }\r
- } else {\r
- // Mark the non-virtual base as seen.\r
- if (!Bases.NonVirtualBases.insert(BaseDecl)) {\r
- // If this non-virtual base has been seen before, then the class has non-\r
- // diamond shaped repeated inheritance.\r
- Flags |= RTTIBuilder::VMI_NonDiamondRepeat;\r
- } else {\r
- if (Bases.VirtualBases.count(BaseDecl))\r
- Flags |= RTTIBuilder::VMI_NonDiamondRepeat;\r
- }\r
- }\r
-\r
- // Walk all bases.\r
- for (CXXRecordDecl::base_class_const_iterator I = BaseDecl->bases_begin(),\r
- E = BaseDecl->bases_end(); I != E; ++I) \r
- Flags |= ComputeVMIClassTypeInfoFlags(I, Bases);\r
- \r
- return Flags;\r
-}\r
-\r
-static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {\r
- unsigned Flags = 0;\r
- SeenBases Bases;\r
- \r
- // Walk all bases.\r
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),\r
- E = RD->bases_end(); I != E; ++I) \r
- Flags |= ComputeVMIClassTypeInfoFlags(I, Bases);\r
- \r
- return Flags;\r
-}\r
-\r
-/// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for\r
-/// classes with bases that do not satisfy the abi::__si_class_type_info \r
-/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.\r
-void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {\r
- llvm::Type *UnsignedIntLTy = \r
- CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);\r
- \r
- // Itanium C++ ABI 2.9.5p6c:\r
- // __flags is a word with flags describing details about the class \r
- // structure, which may be referenced by using the __flags_masks \r
- // enumeration. These flags refer to both direct and indirect bases. \r
- unsigned Flags = ComputeVMIClassTypeInfoFlags(RD);\r
- Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));\r
-\r
- // Itanium C++ ABI 2.9.5p6c:\r
- // __base_count is a word with the number of direct proper base class \r
- // descriptions that follow.\r
- Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases()));\r
- \r
- if (!RD->getNumBases())\r
- return;\r
- \r
- llvm::Type *LongLTy = \r
- CGM.getTypes().ConvertType(CGM.getContext().LongTy);\r
-\r
- // Now add the base class descriptions.\r
- \r
- // Itanium C++ ABI 2.9.5p6c:\r
- // __base_info[] is an array of base class descriptions -- one for every \r
- // direct proper base. Each description is of the type:\r
- //\r
- // struct abi::__base_class_type_info {\r
- // public:\r
- // const __class_type_info *__base_type;\r
- // long __offset_flags;\r
- //\r
- // enum __offset_flags_masks {\r
- // __virtual_mask = 0x1,\r
- // __public_mask = 0x2,\r
- // __offset_shift = 8\r
- // };\r
- // };\r
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),\r
- E = RD->bases_end(); I != E; ++I) {\r
- const CXXBaseSpecifier *Base = I;\r
-\r
- // The __base_type member points to the RTTI for the base type.\r
- Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(Base->getType()));\r
-\r
- const CXXRecordDecl *BaseDecl = \r
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());\r
-\r
- int64_t OffsetFlags = 0;\r
- \r
- // All but the lower 8 bits of __offset_flags are a signed offset. \r
- // For a non-virtual base, this is the offset in the object of the base\r
- // subobject. For a virtual base, this is the offset in the virtual table of\r
- // the virtual base offset for the virtual base referenced (negative).\r
- CharUnits Offset;\r
- if (Base->isVirtual())\r
- Offset = \r
- CGM.getVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl);\r
- else {\r
- const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);\r
- Offset = Layout.getBaseClassOffset(BaseDecl);\r
- };\r
- \r
- OffsetFlags = uint64_t(Offset.getQuantity()) << 8;\r
- \r
- // The low-order byte of __offset_flags contains flags, as given by the \r
- // masks from the enumeration __offset_flags_masks.\r
- if (Base->isVirtual())\r
- OffsetFlags |= BCTI_Virtual;\r
- if (Base->getAccessSpecifier() == AS_public)\r
- OffsetFlags |= BCTI_Public;\r
-\r
- Fields.push_back(llvm::ConstantInt::get(LongLTy, OffsetFlags));\r
- }\r
-}\r
-\r
-/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,\r
-/// used for pointer types.\r
-void RTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) { \r
- Qualifiers Quals;\r
- QualType UnqualifiedPointeeTy = \r
- CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);\r
- \r
- // Itanium C++ ABI 2.9.5p7:\r
- // __flags is a flag word describing the cv-qualification and other \r
- // attributes of the type pointed to\r
- unsigned Flags = ComputeQualifierFlags(Quals);\r
-\r
- // Itanium C++ ABI 2.9.5p7:\r
- // When the abi::__pbase_type_info is for a direct or indirect pointer to an\r
- // incomplete class type, the incomplete target type flag is set. \r
- if (ContainsIncompleteClassType(UnqualifiedPointeeTy))\r
- Flags |= PTI_Incomplete;\r
-\r
- llvm::Type *UnsignedIntLTy = \r
- CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);\r
- Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));\r
- \r
- // Itanium C++ ABI 2.9.5p7:\r
- // __pointee is a pointer to the std::type_info derivation for the \r
- // unqualified type being pointed to.\r
- llvm::Constant *PointeeTypeInfo = \r
- RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);\r
- Fields.push_back(PointeeTypeInfo);\r
-}\r
-\r
-/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info \r
-/// struct, used for member pointer types.\r
-void RTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {\r
- QualType PointeeTy = Ty->getPointeeType();\r
- \r
- Qualifiers Quals;\r
- QualType UnqualifiedPointeeTy = \r
- CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);\r
- \r
- // Itanium C++ ABI 2.9.5p7:\r
- // __flags is a flag word describing the cv-qualification and other \r
- // attributes of the type pointed to.\r
- unsigned Flags = ComputeQualifierFlags(Quals);\r
-\r
- const RecordType *ClassType = cast<RecordType>(Ty->getClass());\r
-\r
- // Itanium C++ ABI 2.9.5p7:\r
- // When the abi::__pbase_type_info is for a direct or indirect pointer to an\r
- // incomplete class type, the incomplete target type flag is set. \r
- if (ContainsIncompleteClassType(UnqualifiedPointeeTy))\r
- Flags |= PTI_Incomplete;\r
-\r
- if (IsIncompleteClassType(ClassType))\r
- Flags |= PTI_ContainingClassIncomplete;\r
- \r
- llvm::Type *UnsignedIntLTy = \r
- CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);\r
- Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));\r
- \r
- // Itanium C++ ABI 2.9.5p7:\r
- // __pointee is a pointer to the std::type_info derivation for the \r
- // unqualified type being pointed to.\r
- llvm::Constant *PointeeTypeInfo = \r
- RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);\r
- Fields.push_back(PointeeTypeInfo);\r
-\r
- // Itanium C++ ABI 2.9.5p9:\r
- // __context is a pointer to an abi::__class_type_info corresponding to the\r
- // class type containing the member pointed to \r
- // (e.g., the "A" in "int A::*").\r
- Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0)));\r
-}\r
-\r
-llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,\r
- bool ForEH) {\r
- // Return a bogus pointer if RTTI is disabled, unless it's for EH.\r
- // FIXME: should we even be calling this method if RTTI is disabled\r
- // and it's not for EH?\r
- if (!ForEH && !getLangOpts().RTTI)\r
- return llvm::Constant::getNullValue(Int8PtrTy);\r
- \r
- if (ForEH && Ty->isObjCObjectPointerType() &&\r
- LangOpts.ObjCRuntime.isGNUFamily())\r
- return ObjCRuntime->GetEHType(Ty);\r
-\r
- return RTTIBuilder(*this).BuildTypeInfo(Ty);\r
-}\r
-\r
-void CodeGenModule::EmitFundamentalRTTIDescriptor(QualType Type) {\r
- QualType PointerType = Context.getPointerType(Type);\r
- QualType PointerTypeConst = Context.getPointerType(Type.withConst());\r
- RTTIBuilder(*this).BuildTypeInfo(Type, true);\r
- RTTIBuilder(*this).BuildTypeInfo(PointerType, true);\r
- RTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true);\r
-}\r
-\r
-void CodeGenModule::EmitFundamentalRTTIDescriptors() {\r
- QualType FundamentalTypes[] = { Context.VoidTy, Context.NullPtrTy,\r
- Context.BoolTy, Context.WCharTy,\r
- Context.CharTy, Context.UnsignedCharTy,\r
- Context.SignedCharTy, Context.ShortTy, \r
- Context.UnsignedShortTy, Context.IntTy,\r
- Context.UnsignedIntTy, Context.LongTy, \r
- Context.UnsignedLongTy, Context.LongLongTy, \r
- Context.UnsignedLongLongTy, Context.FloatTy,\r
- Context.DoubleTy, Context.LongDoubleTy,\r
- Context.Char16Ty, Context.Char32Ty };\r
- for (unsigned i = 0; i < sizeof(FundamentalTypes)/sizeof(QualType); ++i)\r
- EmitFundamentalRTTIDescriptor(FundamentalTypes[i]);\r
-}\r
+//===--- 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]);
+}
#include "CodeGenTypes.h"
#include "CGCXXABI.h"
#include "CGCall.h"
-#include "CGOpenCLRuntime.h"
#include "CGRecordLayout.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
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)
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);
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:
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:
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:
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();
-//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This file implements the tentative parsing portions of the Parser\r
-// interfaces, for ambiguity resolution.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "clang/Parse/Parser.h"\r
-#include "clang/Parse/ParseDiagnostic.h"\r
-#include "clang/Sema/ParsedTemplate.h"\r
-using namespace clang;\r
-\r
-/// isCXXDeclarationStatement - C++-specialized function that disambiguates\r
-/// between a declaration or an expression statement, when parsing function\r
-/// bodies. Returns true for declaration, false for expression.\r
-///\r
-/// declaration-statement:\r
-/// block-declaration\r
-///\r
-/// block-declaration:\r
-/// simple-declaration\r
-/// asm-definition\r
-/// namespace-alias-definition\r
-/// using-declaration\r
-/// using-directive\r
-/// [C++0x] static_assert-declaration\r
-///\r
-/// asm-definition:\r
-/// 'asm' '(' string-literal ')' ';'\r
-///\r
-/// namespace-alias-definition:\r
-/// 'namespace' identifier = qualified-namespace-specifier ';'\r
-///\r
-/// using-declaration:\r
-/// 'using' typename[opt] '::'[opt] nested-name-specifier\r
-/// unqualified-id ';'\r
-/// 'using' '::' unqualified-id ;\r
-///\r
-/// using-directive:\r
-/// 'using' 'namespace' '::'[opt] nested-name-specifier[opt]\r
-/// namespace-name ';'\r
-///\r
-bool Parser::isCXXDeclarationStatement() {\r
- switch (Tok.getKind()) {\r
- // asm-definition\r
- case tok::kw_asm:\r
- // namespace-alias-definition\r
- case tok::kw_namespace:\r
- // using-declaration\r
- // using-directive\r
- case tok::kw_using:\r
- // static_assert-declaration\r
- case tok::kw_static_assert:\r
- case tok::kw__Static_assert:\r
- return true;\r
- // simple-declaration\r
- default:\r
- return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);\r
- }\r
-}\r
-\r
-/// isCXXSimpleDeclaration - C++-specialized function that disambiguates\r
-/// between a simple-declaration or an expression-statement.\r
-/// If during the disambiguation process a parsing error is encountered,\r
-/// the function returns true to let the declaration parsing code handle it.\r
-/// Returns false if the statement is disambiguated as expression.\r
-///\r
-/// simple-declaration:\r
-/// decl-specifier-seq init-declarator-list[opt] ';'\r
-///\r
-/// (if AllowForRangeDecl specified)\r
-/// for ( for-range-declaration : for-range-initializer ) statement\r
-/// for-range-declaration: \r
-/// attribute-specifier-seqopt type-specifier-seq declarator\r
-bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {\r
- // C++ 6.8p1:\r
- // There is an ambiguity in the grammar involving expression-statements and\r
- // declarations: An expression-statement with a function-style explicit type\r
- // conversion (5.2.3) as its leftmost subexpression can be indistinguishable\r
- // from a declaration where the first declarator starts with a '('. In those\r
- // cases the statement is a declaration. [Note: To disambiguate, the whole\r
- // statement might have to be examined to determine if it is an\r
- // expression-statement or a declaration].\r
-\r
- // C++ 6.8p3:\r
- // The disambiguation is purely syntactic; that is, the meaning of the names\r
- // occurring in such a statement, beyond whether they are type-names or not,\r
- // is not generally used in or changed by the disambiguation. Class\r
- // templates are instantiated as necessary to determine if a qualified name\r
- // is a type-name. Disambiguation precedes parsing, and a statement\r
- // disambiguated as a declaration may be an ill-formed declaration.\r
-\r
- // We don't have to parse all of the decl-specifier-seq part. There's only\r
- // an ambiguity if the first decl-specifier is\r
- // simple-type-specifier/typename-specifier followed by a '(', which may\r
- // indicate a function-style cast expression.\r
- // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such\r
- // a case.\r
-\r
- bool InvalidAsDeclaration = false;\r
- TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),\r
- &InvalidAsDeclaration);\r
- if (TPR != TPResult::Ambiguous())\r
- return TPR != TPResult::False(); // Returns true for TPResult::True() or\r
- // TPResult::Error().\r
-\r
- // FIXME: TryParseSimpleDeclaration doesn't look past the first initializer,\r
- // and so gets some cases wrong. We can't carry on if we've already seen\r
- // something which makes this statement invalid as a declaration in this case,\r
- // since it can cause us to misparse valid code. Revisit this once\r
- // TryParseInitDeclaratorList is fixed.\r
- if (InvalidAsDeclaration)\r
- return false;\r
-\r
- // FIXME: Add statistics about the number of ambiguous statements encountered\r
- // and how they were resolved (number of declarations+number of expressions).\r
-\r
- // Ok, we have a simple-type-specifier/typename-specifier followed by a '(',\r
- // or an identifier which doesn't resolve as anything. We need tentative\r
- // parsing...\r
-\r
- TentativeParsingAction PA(*this);\r
- TPR = TryParseSimpleDeclaration(AllowForRangeDecl);\r
- PA.Revert();\r
-\r
- // In case of an error, let the declaration parsing code handle it.\r
- if (TPR == TPResult::Error())\r
- return true;\r
-\r
- // Declarations take precedence over expressions.\r
- if (TPR == TPResult::Ambiguous())\r
- TPR = TPResult::True();\r
-\r
- assert(TPR == TPResult::True() || TPR == TPResult::False());\r
- return TPR == TPResult::True();\r
-}\r
-\r
-/// simple-declaration:\r
-/// decl-specifier-seq init-declarator-list[opt] ';'\r
-///\r
-/// (if AllowForRangeDecl specified)\r
-/// for ( for-range-declaration : for-range-initializer ) statement\r
-/// for-range-declaration: \r
-/// attribute-specifier-seqopt type-specifier-seq declarator\r
-///\r
-Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {\r
- if (Tok.is(tok::kw_typeof))\r
- TryParseTypeofSpecifier();\r
- else {\r
- if (Tok.is(tok::annot_cxxscope))\r
- ConsumeToken();\r
- ConsumeToken();\r
-\r
- if (getLangOpts().ObjC1 && Tok.is(tok::less))\r
- TryParseProtocolQualifiers();\r
- }\r
-\r
- // Two decl-specifiers in a row conclusively disambiguate this as being a\r
- // simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the\r
- // overwhelmingly common case that the next token is a '('.\r
- if (Tok.isNot(tok::l_paren)) {\r
- TPResult TPR = isCXXDeclarationSpecifier();\r
- if (TPR == TPResult::Ambiguous())\r
- return TPResult::True();\r
- if (TPR == TPResult::True() || TPR == TPResult::Error())\r
- return TPR;\r
- assert(TPR == TPResult::False());\r
- }\r
-\r
- TPResult TPR = TryParseInitDeclaratorList();\r
- if (TPR != TPResult::Ambiguous())\r
- return TPR;\r
-\r
- if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon)))\r
- return TPResult::False();\r
-\r
- return TPResult::Ambiguous();\r
-}\r
-\r
-/// init-declarator-list:\r
-/// init-declarator\r
-/// init-declarator-list ',' init-declarator\r
-///\r
-/// init-declarator:\r
-/// declarator initializer[opt]\r
-/// [GNU] declarator simple-asm-expr[opt] attributes[opt] initializer[opt]\r
-///\r
-/// initializer:\r
-/// '=' initializer-clause\r
-/// '(' expression-list ')'\r
-///\r
-/// initializer-clause:\r
-/// assignment-expression\r
-/// '{' initializer-list ','[opt] '}'\r
-/// '{' '}'\r
-///\r
-Parser::TPResult Parser::TryParseInitDeclaratorList() {\r
- while (1) {\r
- // declarator\r
- TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);\r
- if (TPR != TPResult::Ambiguous())\r
- return TPR;\r
-\r
- // [GNU] simple-asm-expr[opt] attributes[opt]\r
- if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))\r
- return TPResult::True();\r
-\r
- // initializer[opt]\r
- if (Tok.is(tok::l_paren)) {\r
- // Parse through the parens.\r
- ConsumeParen();\r
- if (!SkipUntil(tok::r_paren))\r
- return TPResult::Error();\r
- } else if (Tok.is(tok::equal) || isTokIdentifier_in()) {\r
- // MSVC and g++ won't examine the rest of declarators if '=' is \r
- // encountered; they just conclude that we have a declaration.\r
- // EDG parses the initializer completely, which is the proper behavior\r
- // for this case.\r
- //\r
- // At present, Clang follows MSVC and g++, since the parser does not have\r
- // the ability to parse an expression fully without recording the\r
- // results of that parse.\r
- // Also allow 'in' after on objective-c declaration as in: \r
- // for (int (^b)(void) in array). Ideally this should be done in the \r
- // context of parsing for-init-statement of a foreach statement only. But,\r
- // in any other context 'in' is invalid after a declaration and parser\r
- // issues the error regardless of outcome of this decision.\r
- // FIXME. Change if above assumption does not hold.\r
- return TPResult::True();\r
- }\r
-\r
- if (Tok.isNot(tok::comma))\r
- break;\r
- ConsumeToken(); // the comma.\r
- }\r
-\r
- return TPResult::Ambiguous();\r
-}\r
-\r
-/// isCXXConditionDeclaration - Disambiguates between a declaration or an\r
-/// expression for a condition of a if/switch/while/for statement.\r
-/// If during the disambiguation process a parsing error is encountered,\r
-/// the function returns true to let the declaration parsing code handle it.\r
-///\r
-/// condition:\r
-/// expression\r
-/// type-specifier-seq declarator '=' assignment-expression\r
-/// [C++11] type-specifier-seq declarator '=' initializer-clause\r
-/// [C++11] type-specifier-seq declarator braced-init-list\r
-/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]\r
-/// '=' assignment-expression\r
-///\r
-bool Parser::isCXXConditionDeclaration() {\r
- TPResult TPR = isCXXDeclarationSpecifier();\r
- if (TPR != TPResult::Ambiguous())\r
- return TPR != TPResult::False(); // Returns true for TPResult::True() or\r
- // TPResult::Error().\r
-\r
- // FIXME: Add statistics about the number of ambiguous statements encountered\r
- // and how they were resolved (number of declarations+number of expressions).\r
-\r
- // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.\r
- // We need tentative parsing...\r
-\r
- TentativeParsingAction PA(*this);\r
-\r
- // type-specifier-seq\r
- if (Tok.is(tok::kw_typeof))\r
- TryParseTypeofSpecifier();\r
- else {\r
- ConsumeToken();\r
- \r
- if (getLangOpts().ObjC1 && Tok.is(tok::less))\r
- TryParseProtocolQualifiers();\r
- }\r
- assert(Tok.is(tok::l_paren) && "Expected '('");\r
-\r
- // declarator\r
- TPR = TryParseDeclarator(false/*mayBeAbstract*/);\r
-\r
- // In case of an error, let the declaration parsing code handle it.\r
- if (TPR == TPResult::Error())\r
- TPR = TPResult::True();\r
-\r
- if (TPR == TPResult::Ambiguous()) {\r
- // '='\r
- // [GNU] simple-asm-expr[opt] attributes[opt]\r
- if (Tok.is(tok::equal) ||\r
- Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))\r
- TPR = TPResult::True();\r
- else if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace))\r
- TPR = TPResult::True();\r
- else\r
- TPR = TPResult::False();\r
- }\r
-\r
- PA.Revert();\r
-\r
- assert(TPR == TPResult::True() || TPR == TPResult::False());\r
- return TPR == TPResult::True();\r
-}\r
-\r
- /// \brief Determine whether the next set of tokens contains a type-id.\r
- ///\r
- /// The context parameter states what context we're parsing right\r
- /// now, which affects how this routine copes with the token\r
- /// following the type-id. If the context is TypeIdInParens, we have\r
- /// already parsed the '(' and we will cease lookahead when we hit\r
- /// the corresponding ')'. If the context is\r
- /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','\r
- /// before this template argument, and will cease lookahead when we\r
- /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id\r
- /// and false for an expression. If during the disambiguation\r
- /// process a parsing error is encountered, the function returns\r
- /// true to let the declaration parsing code handle it.\r
- ///\r
- /// type-id:\r
- /// type-specifier-seq abstract-declarator[opt]\r
- ///\r
-bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {\r
-\r
- isAmbiguous = false;\r
-\r
- // C++ 8.2p2:\r
- // The ambiguity arising from the similarity between a function-style cast and\r
- // a type-id can occur in different contexts. The ambiguity appears as a\r
- // choice between a function-style cast expression and a declaration of a\r
- // type. The resolution is that any construct that could possibly be a type-id\r
- // in its syntactic context shall be considered a type-id.\r
-\r
- TPResult TPR = isCXXDeclarationSpecifier();\r
- if (TPR != TPResult::Ambiguous())\r
- return TPR != TPResult::False(); // Returns true for TPResult::True() or\r
- // TPResult::Error().\r
-\r
- // FIXME: Add statistics about the number of ambiguous statements encountered\r
- // and how they were resolved (number of declarations+number of expressions).\r
-\r
- // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.\r
- // We need tentative parsing...\r
-\r
- TentativeParsingAction PA(*this);\r
-\r
- // type-specifier-seq\r
- if (Tok.is(tok::kw_typeof))\r
- TryParseTypeofSpecifier();\r
- else {\r
- ConsumeToken();\r
- \r
- if (getLangOpts().ObjC1 && Tok.is(tok::less))\r
- TryParseProtocolQualifiers();\r
- }\r
- \r
- assert(Tok.is(tok::l_paren) && "Expected '('");\r
-\r
- // declarator\r
- TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);\r
-\r
- // In case of an error, let the declaration parsing code handle it.\r
- if (TPR == TPResult::Error())\r
- TPR = TPResult::True();\r
-\r
- if (TPR == TPResult::Ambiguous()) {\r
- // We are supposed to be inside parens, so if after the abstract declarator\r
- // we encounter a ')' this is a type-id, otherwise it's an expression.\r
- if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {\r
- TPR = TPResult::True();\r
- isAmbiguous = true;\r
-\r
- // We are supposed to be inside a template argument, so if after\r
- // the abstract declarator we encounter a '>', '>>' (in C++0x), or\r
- // ',', this is a type-id. Otherwise, it's an expression.\r
- } else if (Context == TypeIdAsTemplateArgument &&\r
- (Tok.is(tok::greater) || Tok.is(tok::comma) ||\r
- (getLangOpts().CPlusPlus0x && Tok.is(tok::greatergreater)))) {\r
- TPR = TPResult::True();\r
- isAmbiguous = true;\r
-\r
- } else\r
- TPR = TPResult::False();\r
- }\r
-\r
- PA.Revert();\r
-\r
- assert(TPR == TPResult::True() || TPR == TPResult::False());\r
- return TPR == TPResult::True();\r
-}\r
-\r
-/// \brief Returns true if this is a C++11 attribute-specifier. Per\r
-/// C++11 [dcl.attr.grammar]p6, two consecutive left square bracket tokens\r
-/// always introduce an attribute. In Objective-C++11, this rule does not\r
-/// apply if either '[' begins a message-send.\r
-///\r
-/// If Disambiguate is true, we try harder to determine whether a '[[' starts\r
-/// an attribute-specifier, and return CAK_InvalidAttributeSpecifier if not.\r
-///\r
-/// If OuterMightBeMessageSend is true, we assume the outer '[' is either an\r
-/// Obj-C message send or the start of an attribute. Otherwise, we assume it\r
-/// is not an Obj-C message send.\r
-///\r
-/// C++11 [dcl.attr.grammar]:\r
-///\r
-/// attribute-specifier:\r
-/// '[' '[' attribute-list ']' ']'\r
-/// alignment-specifier\r
-///\r
-/// attribute-list:\r
-/// attribute[opt]\r
-/// attribute-list ',' attribute[opt]\r
-/// attribute '...'\r
-/// attribute-list ',' attribute '...'\r
-///\r
-/// attribute:\r
-/// attribute-token attribute-argument-clause[opt]\r
-///\r
-/// attribute-token:\r
-/// identifier\r
-/// identifier '::' identifier\r
-///\r
-/// attribute-argument-clause:\r
-/// '(' balanced-token-seq ')'\r
-Parser::CXX11AttributeKind\r
-Parser::isCXX11AttributeSpecifier(bool Disambiguate,\r
- bool OuterMightBeMessageSend) {\r
- if (Tok.is(tok::kw_alignas))\r
- return CAK_AttributeSpecifier;\r
-\r
- if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))\r
- return CAK_NotAttributeSpecifier;\r
-\r
- // No tentative parsing if we don't need to look for ']]' or a lambda.\r
- if (!Disambiguate && !getLangOpts().ObjC1)\r
- return CAK_AttributeSpecifier;\r
-\r
- TentativeParsingAction PA(*this);\r
-\r
- // Opening brackets were checked for above.\r
- ConsumeBracket();\r
-\r
- // Outside Obj-C++11, treat anything with a matching ']]' as an attribute.\r
- if (!getLangOpts().ObjC1) {\r
- ConsumeBracket();\r
-\r
- bool IsAttribute = SkipUntil(tok::r_square, false);\r
- IsAttribute &= Tok.is(tok::r_square);\r
-\r
- PA.Revert();\r
-\r
- return IsAttribute ? CAK_AttributeSpecifier : CAK_InvalidAttributeSpecifier;\r
- }\r
-\r
- // In Obj-C++11, we need to distinguish four situations:\r
- // 1a) int x[[attr]]; C++11 attribute.\r
- // 1b) [[attr]]; C++11 statement attribute.\r
- // 2) int x[[obj](){ return 1; }()]; Lambda in array size/index.\r
- // 3a) int x[[obj get]]; Message send in array size/index.\r
- // 3b) [[Class alloc] init]; Message send in message send.\r
- // 4) [[obj]{ return self; }() doStuff]; Lambda in message send.\r
- // (1) is an attribute, (2) is ill-formed, and (3) and (4) are accepted.\r
-\r
- // If we have a lambda-introducer, then this is definitely not a message send.\r
- // FIXME: If this disambiguation is too slow, fold the tentative lambda parse\r
- // into the tentative attribute parse below.\r
- LambdaIntroducer Intro;\r
- if (!TryParseLambdaIntroducer(Intro)) {\r
- // A lambda cannot end with ']]', and an attribute must.\r
- bool IsAttribute = Tok.is(tok::r_square);\r
-\r
- PA.Revert();\r
-\r
- if (IsAttribute)\r
- // Case 1: C++11 attribute.\r
- return CAK_AttributeSpecifier;\r
-\r
- if (OuterMightBeMessageSend)\r
- // Case 4: Lambda in message send.\r
- return CAK_NotAttributeSpecifier;\r
-\r
- // Case 2: Lambda in array size / index.\r
- return CAK_InvalidAttributeSpecifier;\r
- }\r
-\r
- ConsumeBracket();\r
-\r
- // If we don't have a lambda-introducer, then we have an attribute or a\r
- // message-send.\r
- bool IsAttribute = true;\r
- while (Tok.isNot(tok::r_square)) {\r
- if (Tok.is(tok::comma)) {\r
- // Case 1: Stray commas can only occur in attributes.\r
- PA.Revert();\r
- return CAK_AttributeSpecifier;\r
- }\r
-\r
- // Parse the attribute-token, if present.\r
- // C++11 [dcl.attr.grammar]:\r
- // If a keyword or an alternative token that satisfies the syntactic\r
- // requirements of an identifier is contained in an attribute-token,\r
- // it is considered an identifier.\r
- SourceLocation Loc;\r
- if (!TryParseCXX11AttributeIdentifier(Loc)) {\r
- IsAttribute = false;\r
- break;\r
- }\r
- if (Tok.is(tok::coloncolon)) {\r
- ConsumeToken();\r
- if (!TryParseCXX11AttributeIdentifier(Loc)) {\r
- IsAttribute = false;\r
- break;\r
- }\r
- }\r
-\r
- // Parse the attribute-argument-clause, if present.\r
- if (Tok.is(tok::l_paren)) {\r
- ConsumeParen();\r
- if (!SkipUntil(tok::r_paren, false)) {\r
- IsAttribute = false;\r
- break;\r
- }\r
- }\r
-\r
- if (Tok.is(tok::ellipsis))\r
- ConsumeToken();\r
-\r
- if (Tok.isNot(tok::comma))\r
- break;\r
-\r
- ConsumeToken();\r
- }\r
-\r
- // An attribute must end ']]'.\r
- if (IsAttribute) {\r
- if (Tok.is(tok::r_square)) {\r
- ConsumeBracket();\r
- IsAttribute = Tok.is(tok::r_square);\r
- } else {\r
- IsAttribute = false;\r
- }\r
- }\r
-\r
- PA.Revert();\r
-\r
- if (IsAttribute)\r
- // Case 1: C++11 statement attribute.\r
- return CAK_AttributeSpecifier;\r
-\r
- // Case 3: Message send.\r
- return CAK_NotAttributeSpecifier;\r
-}\r
-\r
-/// declarator:\r
-/// direct-declarator\r
-/// ptr-operator declarator\r
-///\r
-/// direct-declarator:\r
-/// declarator-id\r
-/// direct-declarator '(' parameter-declaration-clause ')'\r
-/// cv-qualifier-seq[opt] exception-specification[opt]\r
-/// direct-declarator '[' constant-expression[opt] ']'\r
-/// '(' declarator ')'\r
-/// [GNU] '(' attributes declarator ')'\r
-///\r
-/// abstract-declarator:\r
-/// ptr-operator abstract-declarator[opt]\r
-/// direct-abstract-declarator\r
-/// ...\r
-///\r
-/// direct-abstract-declarator:\r
-/// direct-abstract-declarator[opt]\r
-/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]\r
-/// exception-specification[opt]\r
-/// direct-abstract-declarator[opt] '[' constant-expression[opt] ']'\r
-/// '(' abstract-declarator ')'\r
-///\r
-/// ptr-operator:\r
-/// '*' cv-qualifier-seq[opt]\r
-/// '&'\r
-/// [C++0x] '&&' [TODO]\r
-/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]\r
-///\r
-/// cv-qualifier-seq:\r
-/// cv-qualifier cv-qualifier-seq[opt]\r
-///\r
-/// cv-qualifier:\r
-/// 'const'\r
-/// 'volatile'\r
-///\r
-/// declarator-id:\r
-/// '...'[opt] id-expression\r
-///\r
-/// id-expression:\r
-/// unqualified-id\r
-/// qualified-id [TODO]\r
-///\r
-/// unqualified-id:\r
-/// identifier\r
-/// operator-function-id [TODO]\r
-/// conversion-function-id [TODO]\r
-/// '~' class-name [TODO]\r
-/// template-id [TODO]\r
-///\r
-Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,\r
- bool mayHaveIdentifier) {\r
- // declarator:\r
- // direct-declarator\r
- // ptr-operator declarator\r
-\r
- while (1) {\r
- if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))\r
- if (TryAnnotateCXXScopeToken(true))\r
- return TPResult::Error();\r
-\r
- if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||\r
- Tok.is(tok::ampamp) ||\r
- (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {\r
- // ptr-operator\r
- ConsumeToken();\r
- while (Tok.is(tok::kw_const) ||\r
- Tok.is(tok::kw_volatile) ||\r
- Tok.is(tok::kw_restrict))\r
- ConsumeToken();\r
- } else {\r
- break;\r
- }\r
- }\r
-\r
- // direct-declarator:\r
- // direct-abstract-declarator:\r
- if (Tok.is(tok::ellipsis))\r
- ConsumeToken();\r
- \r
- if ((Tok.is(tok::identifier) ||\r
- (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) &&\r
- mayHaveIdentifier) {\r
- // declarator-id\r
- if (Tok.is(tok::annot_cxxscope))\r
- ConsumeToken();\r
- else\r
- TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo());\r
- ConsumeToken();\r
- } else if (Tok.is(tok::l_paren)) {\r
- ConsumeParen();\r
- if (mayBeAbstract &&\r
- (Tok.is(tok::r_paren) || // 'int()' is a function.\r
- // 'int(...)' is a function.\r
- (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren)) ||\r
- isDeclarationSpecifier())) { // 'int(int)' is a function.\r
- // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]\r
- // exception-specification[opt]\r
- TPResult TPR = TryParseFunctionDeclarator();\r
- if (TPR != TPResult::Ambiguous())\r
- return TPR;\r
- } else {\r
- // '(' declarator ')'\r
- // '(' attributes declarator ')'\r
- // '(' abstract-declarator ')'\r
- if (Tok.is(tok::kw___attribute) ||\r
- Tok.is(tok::kw___declspec) ||\r
- Tok.is(tok::kw___cdecl) ||\r
- Tok.is(tok::kw___stdcall) ||\r
- Tok.is(tok::kw___fastcall) ||\r
- Tok.is(tok::kw___thiscall) ||\r
- Tok.is(tok::kw___unaligned))\r
- return TPResult::True(); // attributes indicate declaration\r
- TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);\r
- if (TPR != TPResult::Ambiguous())\r
- return TPR;\r
- if (Tok.isNot(tok::r_paren))\r
- return TPResult::False();\r
- ConsumeParen();\r
- }\r
- } else if (!mayBeAbstract) {\r
- return TPResult::False();\r
- }\r
-\r
- while (1) {\r
- TPResult TPR(TPResult::Ambiguous());\r
-\r
- // abstract-declarator: ...\r
- if (Tok.is(tok::ellipsis))\r
- ConsumeToken();\r
-\r
- if (Tok.is(tok::l_paren)) {\r
- // Check whether we have a function declarator or a possible ctor-style\r
- // initializer that follows the declarator. Note that ctor-style\r
- // initializers are not possible in contexts where abstract declarators\r
- // are allowed.\r
- if (!mayBeAbstract && !isCXXFunctionDeclarator())\r
- break;\r
-\r
- // direct-declarator '(' parameter-declaration-clause ')'\r
- // cv-qualifier-seq[opt] exception-specification[opt]\r
- ConsumeParen();\r
- TPR = TryParseFunctionDeclarator();\r
- } else if (Tok.is(tok::l_square)) {\r
- // direct-declarator '[' constant-expression[opt] ']'\r
- // direct-abstract-declarator[opt] '[' constant-expression[opt] ']'\r
- TPR = TryParseBracketDeclarator();\r
- } else {\r
- break;\r
- }\r
-\r
- if (TPR != TPResult::Ambiguous())\r
- return TPR;\r
- }\r
-\r
- return TPResult::Ambiguous();\r
-}\r
-\r
-Parser::TPResult \r
-Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {\r
- switch (Kind) {\r
- // Obviously starts an expression.\r
- case tok::numeric_constant:\r
- case tok::char_constant:\r
- case tok::wide_char_constant:\r
- case tok::utf16_char_constant:\r
- case tok::utf32_char_constant:\r
- case tok::string_literal:\r
- case tok::wide_string_literal:\r
- case tok::utf8_string_literal:\r
- case tok::utf16_string_literal:\r
- case tok::utf32_string_literal:\r
- case tok::l_square:\r
- case tok::l_paren:\r
- case tok::amp:\r
- case tok::ampamp:\r
- case tok::star:\r
- case tok::plus:\r
- case tok::plusplus:\r
- case tok::minus:\r
- case tok::minusminus:\r
- case tok::tilde:\r
- case tok::exclaim:\r
- case tok::kw_sizeof:\r
- case tok::kw___func__:\r
- case tok::kw_const_cast:\r
- case tok::kw_delete:\r
- case tok::kw_dynamic_cast:\r
- case tok::kw_false:\r
- case tok::kw_new:\r
- case tok::kw_operator:\r
- case tok::kw_reinterpret_cast:\r
- case tok::kw_static_cast:\r
- case tok::kw_this:\r
- case tok::kw_throw:\r
- case tok::kw_true:\r
- case tok::kw_typeid:\r
- case tok::kw_alignof:\r
- case tok::kw_noexcept:\r
- case tok::kw_nullptr:\r
- case tok::kw__Alignof:\r
- case tok::kw___null:\r
- case tok::kw___alignof:\r
- case tok::kw___builtin_choose_expr:\r
- case tok::kw___builtin_offsetof:\r
- case tok::kw___builtin_types_compatible_p:\r
- case tok::kw___builtin_va_arg:\r
- case tok::kw___imag:\r
- case tok::kw___real:\r
- case tok::kw___FUNCTION__:\r
- case tok::kw_L__FUNCTION__:\r
- case tok::kw___PRETTY_FUNCTION__:\r
- case tok::kw___has_nothrow_assign:\r
- case tok::kw___has_nothrow_copy:\r
- case tok::kw___has_nothrow_constructor:\r
- case tok::kw___has_trivial_assign:\r
- case tok::kw___has_trivial_copy:\r
- case tok::kw___has_trivial_constructor:\r
- case tok::kw___has_trivial_destructor:\r
- case tok::kw___has_virtual_destructor:\r
- case tok::kw___is_abstract:\r
- case tok::kw___is_base_of:\r
- case tok::kw___is_class:\r
- case tok::kw___is_convertible_to:\r
- case tok::kw___is_empty:\r
- case tok::kw___is_enum:\r
- case tok::kw___is_interface_class:\r
- case tok::kw___is_final:\r
- case tok::kw___is_literal:\r
- case tok::kw___is_literal_type:\r
- case tok::kw___is_pod:\r
- case tok::kw___is_polymorphic:\r
- case tok::kw___is_trivial:\r
- case tok::kw___is_trivially_assignable:\r
- case tok::kw___is_trivially_constructible:\r
- case tok::kw___is_trivially_copyable:\r
- case tok::kw___is_union:\r
- case tok::kw___uuidof:\r
- return TPResult::True();\r
- \r
- // Obviously starts a type-specifier-seq:\r
- case tok::kw_char:\r
- case tok::kw_const:\r
- case tok::kw_double:\r
- case tok::kw_enum:\r
- case tok::kw_half:\r
- case tok::kw_float:\r
- case tok::kw_int:\r
- case tok::kw_long:\r
- case tok::kw___int64:\r
- case tok::kw___int128:\r
- case tok::kw_restrict:\r
- case tok::kw_short:\r
- case tok::kw_signed:\r
- case tok::kw_struct:\r
- case tok::kw_union:\r
- case tok::kw_unsigned:\r
- case tok::kw_void:\r
- case tok::kw_volatile:\r
- case tok::kw__Bool:\r
- case tok::kw__Complex:\r
- case tok::kw_class:\r
- case tok::kw_typename:\r
- case tok::kw_wchar_t:\r
- case tok::kw_char16_t:\r
- case tok::kw_char32_t:\r
- case tok::kw___underlying_type:\r
- case tok::kw_thread_local:\r
- case tok::kw__Decimal32:\r
- case tok::kw__Decimal64:\r
- case tok::kw__Decimal128:\r
- case tok::kw___thread:\r
- case tok::kw_typeof:\r
- case tok::kw___cdecl:\r
- case tok::kw___stdcall:\r
- case tok::kw___fastcall:\r
- case tok::kw___thiscall:\r
- case tok::kw___unaligned:\r
- case tok::kw___vector:\r
- case tok::kw___pixel:\r
- case tok::kw__Atomic:\r
- case tok::kw_image1d_t:\r
- case tok::kw_image1d_array_t:\r
- case tok::kw_image1d_buffer_t:\r
- case tok::kw_image2d_t:\r
- case tok::kw_image2d_array_t:\r
- case tok::kw_image3d_t:\r
- case tok::kw___unknown_anytype:\r
- return TPResult::False();\r
-\r
- default:\r
- break;\r
- }\r
- \r
- return TPResult::Ambiguous();\r
-}\r
-\r
-bool Parser::isTentativelyDeclared(IdentifierInfo *II) {\r
- return std::find(TentativelyDeclaredIdentifiers.begin(),\r
- TentativelyDeclaredIdentifiers.end(), II)\r
- != TentativelyDeclaredIdentifiers.end();\r
-}\r
-\r
-/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration\r
-/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could\r
-/// be either a decl-specifier or a function-style cast, and TPResult::Error()\r
-/// if a parsing error was found and reported.\r
-///\r
-/// If HasMissingTypename is provided, a name with a dependent scope specifier\r
-/// will be treated as ambiguous if the 'typename' keyword is missing. If this\r
-/// happens, *HasMissingTypename will be set to 'true'. This will also be used\r
-/// as an indicator that undeclared identifiers (which will trigger a later\r
-/// parse error) should be treated as types. Returns TPResult::Ambiguous() in\r
-/// such cases.\r
-///\r
-/// decl-specifier:\r
-/// storage-class-specifier\r
-/// type-specifier\r
-/// function-specifier\r
-/// 'friend'\r
-/// 'typedef'\r
-/// [C++0x] 'constexpr'\r
-/// [GNU] attributes declaration-specifiers[opt]\r
-///\r
-/// storage-class-specifier:\r
-/// 'register'\r
-/// 'static'\r
-/// 'extern'\r
-/// 'mutable'\r
-/// 'auto'\r
-/// [GNU] '__thread'\r
-///\r
-/// function-specifier:\r
-/// 'inline'\r
-/// 'virtual'\r
-/// 'explicit'\r
-///\r
-/// typedef-name:\r
-/// identifier\r
-///\r
-/// type-specifier:\r
-/// simple-type-specifier\r
-/// class-specifier\r
-/// enum-specifier\r
-/// elaborated-type-specifier\r
-/// typename-specifier\r
-/// cv-qualifier\r
-///\r
-/// simple-type-specifier:\r
-/// '::'[opt] nested-name-specifier[opt] type-name\r
-/// '::'[opt] nested-name-specifier 'template'\r
-/// simple-template-id [TODO]\r
-/// 'char'\r
-/// 'wchar_t'\r
-/// 'bool'\r
-/// 'short'\r
-/// 'int'\r
-/// 'long'\r
-/// 'signed'\r
-/// 'unsigned'\r
-/// 'float'\r
-/// 'double'\r
-/// 'void'\r
-/// [GNU] typeof-specifier\r
-/// [GNU] '_Complex'\r
-/// [C++0x] 'auto' [TODO]\r
-/// [C++0x] 'decltype' ( expression )\r
-///\r
-/// type-name:\r
-/// class-name\r
-/// enum-name\r
-/// typedef-name\r
-///\r
-/// elaborated-type-specifier:\r
-/// class-key '::'[opt] nested-name-specifier[opt] identifier\r
-/// class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]\r
-/// simple-template-id\r
-/// 'enum' '::'[opt] nested-name-specifier[opt] identifier\r
-///\r
-/// enum-name:\r
-/// identifier\r
-///\r
-/// enum-specifier:\r
-/// 'enum' identifier[opt] '{' enumerator-list[opt] '}'\r
-/// 'enum' identifier[opt] '{' enumerator-list ',' '}'\r
-///\r
-/// class-specifier:\r
-/// class-head '{' member-specification[opt] '}'\r
-///\r
-/// class-head:\r
-/// class-key identifier[opt] base-clause[opt]\r
-/// class-key nested-name-specifier identifier base-clause[opt]\r
-/// class-key nested-name-specifier[opt] simple-template-id\r
-/// base-clause[opt]\r
-///\r
-/// class-key:\r
-/// 'class'\r
-/// 'struct'\r
-/// 'union'\r
-///\r
-/// cv-qualifier:\r
-/// 'const'\r
-/// 'volatile'\r
-/// [GNU] restrict\r
-///\r
-Parser::TPResult\r
-Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,\r
- bool *HasMissingTypename) {\r
- switch (Tok.getKind()) {\r
- case tok::identifier: {\r
- // Check for need to substitute AltiVec __vector keyword\r
- // for "vector" identifier.\r
- if (TryAltiVecVectorToken())\r
- return TPResult::True();\r
-\r
- const Token &Next = NextToken();\r
- // In 'foo bar', 'foo' is always a type name outside of Objective-C.\r
- if (!getLangOpts().ObjC1 && Next.is(tok::identifier))\r
- return TPResult::True();\r
-\r
- if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) {\r
- // Determine whether this is a valid expression. If not, we will hit\r
- // a parse error one way or another. In that case, tell the caller that\r
- // this is ambiguous. Typo-correct to type and expression keywords and\r
- // to types and identifiers, in order to try to recover from errors.\r
- CorrectionCandidateCallback TypoCorrection;\r
- TypoCorrection.WantRemainingKeywords = false;\r
- switch (TryAnnotateName(false /* no nested name specifier */,\r
- &TypoCorrection)) {\r
- case ANK_Error:\r
- return TPResult::Error();\r
- case ANK_TentativeDecl:\r
- return TPResult::False();\r
- case ANK_TemplateName:\r
- // A bare type template-name which can't be a template template\r
- // argument is an error, and was probably intended to be a type.\r
- return GreaterThanIsOperator ? TPResult::True() : TPResult::False();\r
- case ANK_Unresolved:\r
- return HasMissingTypename ? TPResult::Ambiguous() : TPResult::False();\r
- case ANK_Success:\r
- break;\r
- }\r
- assert(Tok.isNot(tok::identifier) &&\r
- "TryAnnotateName succeeded without producing an annotation");\r
- } else {\r
- // This might possibly be a type with a dependent scope specifier and\r
- // a missing 'typename' keyword. Don't use TryAnnotateName in this case,\r
- // since it will annotate as a primary expression, and we want to use the\r
- // "missing 'typename'" logic.\r
- if (TryAnnotateTypeOrScopeToken())\r
- return TPResult::Error();\r
- // If annotation failed, assume it's a non-type.\r
- // FIXME: If this happens due to an undeclared identifier, treat it as\r
- // ambiguous.\r
- if (Tok.is(tok::identifier))\r
- return TPResult::False();\r
- }\r
-\r
- // We annotated this token as something. Recurse to handle whatever we got.\r
- return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);\r
- }\r
-\r
- case tok::kw_typename: // typename T::type\r
- // Annotate typenames and C++ scope specifiers. If we get one, just\r
- // recurse to handle whatever we get.\r
- if (TryAnnotateTypeOrScopeToken())\r
- return TPResult::Error();\r
- return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);\r
-\r
- case tok::coloncolon: { // ::foo::bar\r
- const Token &Next = NextToken();\r
- if (Next.is(tok::kw_new) || // ::new\r
- Next.is(tok::kw_delete)) // ::delete\r
- return TPResult::False();\r
- }\r
- // Fall through.\r
- case tok::kw_decltype:\r
- // Annotate typenames and C++ scope specifiers. If we get one, just\r
- // recurse to handle whatever we get.\r
- if (TryAnnotateTypeOrScopeToken())\r
- return TPResult::Error();\r
- return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);\r
-\r
- // decl-specifier:\r
- // storage-class-specifier\r
- // type-specifier\r
- // function-specifier\r
- // 'friend'\r
- // 'typedef'\r
- // 'constexpr'\r
- case tok::kw_friend:\r
- case tok::kw_typedef:\r
- case tok::kw_constexpr:\r
- // storage-class-specifier\r
- case tok::kw_register:\r
- case tok::kw_static:\r
- case tok::kw_extern:\r
- case tok::kw_mutable:\r
- case tok::kw_auto:\r
- case tok::kw___thread:\r
- // function-specifier\r
- case tok::kw_inline:\r
- case tok::kw_virtual:\r
- case tok::kw_explicit:\r
-\r
- // Modules\r
- case tok::kw___module_private__:\r
-\r
- // Debugger support\r
- case tok::kw___unknown_anytype:\r
- \r
- // type-specifier:\r
- // simple-type-specifier\r
- // class-specifier\r
- // enum-specifier\r
- // elaborated-type-specifier\r
- // typename-specifier\r
- // cv-qualifier\r
-\r
- // class-specifier\r
- // elaborated-type-specifier\r
- case tok::kw_class:\r
- case tok::kw_struct:\r
- case tok::kw_union:\r
- // enum-specifier\r
- case tok::kw_enum:\r
- // cv-qualifier\r
- case tok::kw_const:\r
- case tok::kw_volatile:\r
-\r
- // GNU\r
- case tok::kw_restrict:\r
- case tok::kw__Complex:\r
- case tok::kw___attribute:\r
- return TPResult::True();\r
-\r
- // Microsoft\r
- case tok::kw___declspec:\r
- case tok::kw___cdecl:\r
- case tok::kw___stdcall:\r
- case tok::kw___fastcall:\r
- case tok::kw___thiscall:\r
- case tok::kw___w64:\r
- case tok::kw___ptr64:\r
- case tok::kw___ptr32:\r
- case tok::kw___forceinline:\r
- case tok::kw___unaligned:\r
- return TPResult::True();\r
-\r
- // Borland\r
- case tok::kw___pascal:\r
- return TPResult::True();\r
- \r
- // AltiVec\r
- case tok::kw___vector:\r
- return TPResult::True();\r
-\r
- case tok::annot_template_id: {\r
- TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);\r
- if (TemplateId->Kind != TNK_Type_template)\r
- return TPResult::False();\r
- CXXScopeSpec SS;\r
- AnnotateTemplateIdTokenAsType();\r
- assert(Tok.is(tok::annot_typename));\r
- goto case_typename;\r
- }\r
-\r
- case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed\r
- // We've already annotated a scope; try to annotate a type.\r
- if (TryAnnotateTypeOrScopeToken())\r
- return TPResult::Error();\r
- if (!Tok.is(tok::annot_typename)) {\r
- // If the next token is an identifier or a type qualifier, then this\r
- // can't possibly be a valid expression either.\r
- if (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier)) {\r
- CXXScopeSpec SS;\r
- Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),\r
- Tok.getAnnotationRange(),\r
- SS);\r
- if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) {\r
- TentativeParsingAction PA(*this);\r
- ConsumeToken();\r
- ConsumeToken();\r
- bool isIdentifier = Tok.is(tok::identifier);\r
- TPResult TPR = TPResult::False();\r
- if (!isIdentifier)\r
- TPR = isCXXDeclarationSpecifier(BracedCastResult,\r
- HasMissingTypename);\r
- PA.Revert();\r
-\r
- if (isIdentifier ||\r
- TPR == TPResult::True() || TPR == TPResult::Error())\r
- return TPResult::Error();\r
-\r
- if (HasMissingTypename) {\r
- // We can't tell whether this is a missing 'typename' or a valid\r
- // expression.\r
- *HasMissingTypename = true;\r
- return TPResult::Ambiguous();\r
- }\r
- } else {\r
- // Try to resolve the name. If it doesn't exist, assume it was\r
- // intended to name a type and keep disambiguating.\r
- switch (TryAnnotateName(false /* SS is not dependent */)) {\r
- case ANK_Error:\r
- return TPResult::Error();\r
- case ANK_TentativeDecl:\r
- return TPResult::False();\r
- case ANK_TemplateName:\r
- // A bare type template-name which can't be a template template\r
- // argument is an error, and was probably intended to be a type.\r
- return GreaterThanIsOperator ? TPResult::True() : TPResult::False();\r
- case ANK_Unresolved:\r
- return HasMissingTypename ? TPResult::Ambiguous()\r
- : TPResult::False();\r
- case ANK_Success:\r
- // Annotated it, check again.\r
- assert(Tok.isNot(tok::annot_cxxscope) ||\r
- NextToken().isNot(tok::identifier));\r
- return isCXXDeclarationSpecifier(BracedCastResult,\r
- HasMissingTypename);\r
- }\r
- }\r
- }\r
- return TPResult::False();\r
- }\r
- // If that succeeded, fallthrough into the generic simple-type-id case.\r
-\r
- // The ambiguity resides in a simple-type-specifier/typename-specifier\r
- // followed by a '('. The '(' could either be the start of:\r
- //\r
- // direct-declarator:\r
- // '(' declarator ')'\r
- //\r
- // direct-abstract-declarator:\r
- // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]\r
- // exception-specification[opt]\r
- // '(' abstract-declarator ')'\r
- //\r
- // or part of a function-style cast expression:\r
- //\r
- // simple-type-specifier '(' expression-list[opt] ')'\r
- //\r
-\r
- // simple-type-specifier:\r
-\r
- case tok::annot_typename:\r
- case_typename:\r
- // In Objective-C, we might have a protocol-qualified type.\r
- if (getLangOpts().ObjC1 && NextToken().is(tok::less)) {\r
- // Tentatively parse the \r
- TentativeParsingAction PA(*this);\r
- ConsumeToken(); // The type token\r
- \r
- TPResult TPR = TryParseProtocolQualifiers();\r
- bool isFollowedByParen = Tok.is(tok::l_paren);\r
- bool isFollowedByBrace = Tok.is(tok::l_brace);\r
- \r
- PA.Revert();\r
- \r
- if (TPR == TPResult::Error())\r
- return TPResult::Error();\r
- \r
- if (isFollowedByParen)\r
- return TPResult::Ambiguous();\r
-\r
- if (getLangOpts().CPlusPlus0x && isFollowedByBrace)\r
- return BracedCastResult;\r
- \r
- return TPResult::True();\r
- }\r
- \r
- case tok::kw_char:\r
- case tok::kw_wchar_t:\r
- case tok::kw_char16_t:\r
- case tok::kw_char32_t:\r
- case tok::kw_bool:\r
- case tok::kw_short:\r
- case tok::kw_int:\r
- case tok::kw_long:\r
- case tok::kw___int64:\r
- case tok::kw___int128:\r
- case tok::kw_signed:\r
- case tok::kw_unsigned:\r
- case tok::kw_half:\r
- case tok::kw_float:\r
- case tok::kw_double:\r
- case tok::kw_void:\r
- case tok::annot_decltype:\r
- if (NextToken().is(tok::l_paren))\r
- return TPResult::Ambiguous();\r
-\r
- // This is a function-style cast in all cases we disambiguate other than\r
- // one:\r
- // struct S {\r
- // enum E : int { a = 4 }; // enum\r
- // enum E : int { 4 }; // bit-field\r
- // };\r
- if (getLangOpts().CPlusPlus0x && NextToken().is(tok::l_brace))\r
- return BracedCastResult;\r
-\r
- if (isStartOfObjCClassMessageMissingOpenBracket())\r
- return TPResult::False();\r
- \r
- return TPResult::True();\r
-\r
- // GNU typeof support.\r
- case tok::kw_typeof: {\r
- if (NextToken().isNot(tok::l_paren))\r
- return TPResult::True();\r
-\r
- TentativeParsingAction PA(*this);\r
-\r
- TPResult TPR = TryParseTypeofSpecifier();\r
- bool isFollowedByParen = Tok.is(tok::l_paren);\r
- bool isFollowedByBrace = Tok.is(tok::l_brace);\r
-\r
- PA.Revert();\r
-\r
- if (TPR == TPResult::Error())\r
- return TPResult::Error();\r
-\r
- if (isFollowedByParen)\r
- return TPResult::Ambiguous();\r
-\r
- if (getLangOpts().CPlusPlus0x && isFollowedByBrace)\r
- return BracedCastResult;\r
-\r
- return TPResult::True();\r
- }\r
-\r
- // C++0x type traits support\r
- case tok::kw___underlying_type:\r
- return TPResult::True();\r
-\r
- // C11 _Atomic\r
- case tok::kw__Atomic:\r
- return TPResult::True();\r
-\r
- default:\r
- return TPResult::False();\r
- }\r
-}\r
-\r
-/// [GNU] typeof-specifier:\r
-/// 'typeof' '(' expressions ')'\r
-/// 'typeof' '(' type-name ')'\r
-///\r
-Parser::TPResult Parser::TryParseTypeofSpecifier() {\r
- assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!");\r
- ConsumeToken();\r
-\r
- assert(Tok.is(tok::l_paren) && "Expected '('");\r
- // Parse through the parens after 'typeof'.\r
- ConsumeParen();\r
- if (!SkipUntil(tok::r_paren))\r
- return TPResult::Error();\r
-\r
- return TPResult::Ambiguous();\r
-}\r
-\r
-/// [ObjC] protocol-qualifiers:\r
-//// '<' identifier-list '>'\r
-Parser::TPResult Parser::TryParseProtocolQualifiers() {\r
- assert(Tok.is(tok::less) && "Expected '<' for qualifier list");\r
- ConsumeToken();\r
- do {\r
- if (Tok.isNot(tok::identifier))\r
- return TPResult::Error();\r
- ConsumeToken();\r
- \r
- if (Tok.is(tok::comma)) {\r
- ConsumeToken();\r
- continue;\r
- }\r
- \r
- if (Tok.is(tok::greater)) {\r
- ConsumeToken();\r
- return TPResult::Ambiguous();\r
- }\r
- } while (false);\r
- \r
- return TPResult::Error();\r
-}\r
-\r
-Parser::TPResult\r
-Parser::TryParseDeclarationSpecifier(bool *HasMissingTypename) {\r
- TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),\r
- HasMissingTypename);\r
- if (TPR != TPResult::Ambiguous())\r
- return TPR;\r
-\r
- if (Tok.is(tok::kw_typeof))\r
- TryParseTypeofSpecifier();\r
- else {\r
- if (Tok.is(tok::annot_cxxscope))\r
- ConsumeToken();\r
- ConsumeToken();\r
- \r
- if (getLangOpts().ObjC1 && Tok.is(tok::less))\r
- TryParseProtocolQualifiers();\r
- }\r
-\r
- return TPResult::Ambiguous();\r
-}\r
-\r
-/// isCXXFunctionDeclarator - Disambiguates between a function declarator or\r
-/// a constructor-style initializer, when parsing declaration statements.\r
-/// Returns true for function declarator and false for constructor-style\r
-/// initializer.\r
-/// If during the disambiguation process a parsing error is encountered,\r
-/// the function returns true to let the declaration parsing code handle it.\r
-///\r
-/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]\r
-/// exception-specification[opt]\r
-///\r
-bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) {\r
-\r
- // C++ 8.2p1:\r
- // The ambiguity arising from the similarity between a function-style cast and\r
- // a declaration mentioned in 6.8 can also occur in the context of a\r
- // declaration. In that context, the choice is between a function declaration\r
- // with a redundant set of parentheses around a parameter name and an object\r
- // declaration with a function-style cast as the initializer. Just as for the\r
- // ambiguities mentioned in 6.8, the resolution is to consider any construct\r
- // that could possibly be a declaration a declaration.\r
-\r
- TentativeParsingAction PA(*this);\r
-\r
- ConsumeParen();\r
- bool InvalidAsDeclaration = false;\r
- TPResult TPR = TryParseParameterDeclarationClause(&InvalidAsDeclaration);\r
- if (TPR == TPResult::Ambiguous()) {\r
- if (Tok.isNot(tok::r_paren))\r
- TPR = TPResult::False();\r
- else {\r
- const Token &Next = NextToken();\r
- if (Next.is(tok::amp) || Next.is(tok::ampamp) ||\r
- Next.is(tok::kw_const) || Next.is(tok::kw_volatile) ||\r
- Next.is(tok::kw_throw) || Next.is(tok::kw_noexcept) ||\r
- Next.is(tok::l_square) || isCXX0XVirtSpecifier(Next) ||\r
- Next.is(tok::l_brace) || Next.is(tok::kw_try) ||\r
- Next.is(tok::equal) || Next.is(tok::arrow))\r
- // The next token cannot appear after a constructor-style initializer,\r
- // and can appear next in a function definition. This must be a function\r
- // declarator.\r
- TPR = TPResult::True();\r
- else if (InvalidAsDeclaration)\r
- // Use the absence of 'typename' as a tie-breaker.\r
- TPR = TPResult::False();\r
- }\r
- }\r
-\r
- PA.Revert();\r
-\r
- if (IsAmbiguous && TPR == TPResult::Ambiguous())\r
- *IsAmbiguous = true;\r
-\r
- // In case of an error, let the declaration parsing code handle it.\r
- return TPR != TPResult::False();\r
-}\r
-\r
-/// parameter-declaration-clause:\r
-/// parameter-declaration-list[opt] '...'[opt]\r
-/// parameter-declaration-list ',' '...'\r
-///\r
-/// parameter-declaration-list:\r
-/// parameter-declaration\r
-/// parameter-declaration-list ',' parameter-declaration\r
-///\r
-/// parameter-declaration:\r
-/// attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]\r
-/// attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]\r
-/// '=' assignment-expression\r
-/// attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]\r
-/// attributes[opt]\r
-/// attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]\r
-/// attributes[opt] '=' assignment-expression\r
-///\r
-Parser::TPResult\r
-Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration) {\r
-\r
- if (Tok.is(tok::r_paren))\r
- return TPResult::Ambiguous();\r
-\r
- // parameter-declaration-list[opt] '...'[opt]\r
- // parameter-declaration-list ',' '...'\r
- //\r
- // parameter-declaration-list:\r
- // parameter-declaration\r
- // parameter-declaration-list ',' parameter-declaration\r
- //\r
- while (1) {\r
- // '...'[opt]\r
- if (Tok.is(tok::ellipsis)) {\r
- ConsumeToken();\r
- if (Tok.is(tok::r_paren))\r
- return TPResult::True(); // '...)' is a sign of a function declarator.\r
- else\r
- return TPResult::False();\r
- }\r
-\r
- // An attribute-specifier-seq here is a sign of a function declarator.\r
- if (isCXX11AttributeSpecifier(/*Disambiguate*/false,\r
- /*OuterMightBeMessageSend*/true))\r
- return TPResult::True();\r
-\r
- ParsedAttributes attrs(AttrFactory);\r
- MaybeParseMicrosoftAttributes(attrs);\r
-\r
- // decl-specifier-seq\r
- // A parameter-declaration's initializer must be preceded by an '=', so\r
- // decl-specifier-seq '{' is not a parameter in C++11.\r
- TPResult TPR = TryParseDeclarationSpecifier(InvalidAsDeclaration);\r
- if (TPR != TPResult::Ambiguous())\r
- return TPR;\r
-\r
- // declarator\r
- // abstract-declarator[opt]\r
- TPR = TryParseDeclarator(true/*mayBeAbstract*/);\r
- if (TPR != TPResult::Ambiguous())\r
- return TPR;\r
-\r
- // [GNU] attributes[opt]\r
- if (Tok.is(tok::kw___attribute))\r
- return TPResult::True();\r
-\r
- if (Tok.is(tok::equal)) {\r
- // '=' assignment-expression\r
- // Parse through assignment-expression.\r
- if (!SkipUntil(tok::comma, tok::r_paren, true/*StopAtSemi*/,\r
- true/*DontConsume*/))\r
- return TPResult::Error();\r
- }\r
-\r
- if (Tok.is(tok::ellipsis)) {\r
- ConsumeToken();\r
- if (Tok.is(tok::r_paren))\r
- return TPResult::True(); // '...)' is a sign of a function declarator.\r
- else\r
- return TPResult::False();\r
- }\r
-\r
- if (Tok.isNot(tok::comma))\r
- break;\r
- ConsumeToken(); // the comma.\r
- }\r
-\r
- return TPResult::Ambiguous();\r
-}\r
-\r
-/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue\r
-/// parsing as a function declarator.\r
-/// If TryParseFunctionDeclarator fully parsed the function declarator, it will\r
-/// return TPResult::Ambiguous(), otherwise it will return either False() or\r
-/// Error().\r
-///\r
-/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]\r
-/// exception-specification[opt]\r
-///\r
-/// exception-specification:\r
-/// 'throw' '(' type-id-list[opt] ')'\r
-///\r
-Parser::TPResult Parser::TryParseFunctionDeclarator() {\r
-\r
- // The '(' is already parsed.\r
-\r
- TPResult TPR = TryParseParameterDeclarationClause();\r
- if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))\r
- TPR = TPResult::False();\r
-\r
- if (TPR == TPResult::False() || TPR == TPResult::Error())\r
- return TPR;\r
-\r
- // Parse through the parens.\r
- if (!SkipUntil(tok::r_paren))\r
- return TPResult::Error();\r
-\r
- // cv-qualifier-seq\r
- while (Tok.is(tok::kw_const) ||\r
- Tok.is(tok::kw_volatile) ||\r
- Tok.is(tok::kw_restrict) )\r
- ConsumeToken();\r
-\r
- // ref-qualifier[opt]\r
- if (Tok.is(tok::amp) || Tok.is(tok::ampamp))\r
- ConsumeToken();\r
- \r
- // exception-specification\r
- if (Tok.is(tok::kw_throw)) {\r
- ConsumeToken();\r
- if (Tok.isNot(tok::l_paren))\r
- return TPResult::Error();\r
-\r
- // Parse through the parens after 'throw'.\r
- ConsumeParen();\r
- if (!SkipUntil(tok::r_paren))\r
- return TPResult::Error();\r
- }\r
- if (Tok.is(tok::kw_noexcept)) {\r
- ConsumeToken();\r
- // Possibly an expression as well.\r
- if (Tok.is(tok::l_paren)) {\r
- // Find the matching rparen.\r
- ConsumeParen();\r
- if (!SkipUntil(tok::r_paren))\r
- return TPResult::Error();\r
- }\r
- }\r
-\r
- return TPResult::Ambiguous();\r
-}\r
-\r
-/// '[' constant-expression[opt] ']'\r
-///\r
-Parser::TPResult Parser::TryParseBracketDeclarator() {\r
- ConsumeBracket();\r
- if (!SkipUntil(tok::r_square))\r
- return TPResult::Error();\r
-\r
- return TPResult::Ambiguous();\r
-}\r
+//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the tentative parsing portions of the Parser
+// interfaces, for ambiguity resolution.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Sema/ParsedTemplate.h"
+using namespace clang;
+
+/// isCXXDeclarationStatement - C++-specialized function that disambiguates
+/// between a declaration or an expression statement, when parsing function
+/// bodies. Returns true for declaration, false for expression.
+///
+/// declaration-statement:
+/// block-declaration
+///
+/// block-declaration:
+/// simple-declaration
+/// asm-definition
+/// namespace-alias-definition
+/// using-declaration
+/// using-directive
+/// [C++0x] static_assert-declaration
+///
+/// asm-definition:
+/// 'asm' '(' string-literal ')' ';'
+///
+/// namespace-alias-definition:
+/// 'namespace' identifier = qualified-namespace-specifier ';'
+///
+/// using-declaration:
+/// 'using' typename[opt] '::'[opt] nested-name-specifier
+/// unqualified-id ';'
+/// 'using' '::' unqualified-id ;
+///
+/// using-directive:
+/// 'using' 'namespace' '::'[opt] nested-name-specifier[opt]
+/// namespace-name ';'
+///
+bool Parser::isCXXDeclarationStatement() {
+ switch (Tok.getKind()) {
+ // asm-definition
+ case tok::kw_asm:
+ // namespace-alias-definition
+ case tok::kw_namespace:
+ // using-declaration
+ // using-directive
+ case tok::kw_using:
+ // static_assert-declaration
+ case tok::kw_static_assert:
+ case tok::kw__Static_assert:
+ return true;
+ // simple-declaration
+ default:
+ return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);
+ }
+}
+
+/// isCXXSimpleDeclaration - C++-specialized function that disambiguates
+/// between a simple-declaration or an expression-statement.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+/// Returns false if the statement is disambiguated as expression.
+///
+/// simple-declaration:
+/// decl-specifier-seq init-declarator-list[opt] ';'
+///
+/// (if AllowForRangeDecl specified)
+/// for ( for-range-declaration : for-range-initializer ) statement
+/// for-range-declaration:
+/// attribute-specifier-seqopt type-specifier-seq declarator
+bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
+ // C++ 6.8p1:
+ // There is an ambiguity in the grammar involving expression-statements and
+ // declarations: An expression-statement with a function-style explicit type
+ // conversion (5.2.3) as its leftmost subexpression can be indistinguishable
+ // from a declaration where the first declarator starts with a '('. In those
+ // cases the statement is a declaration. [Note: To disambiguate, the whole
+ // statement might have to be examined to determine if it is an
+ // expression-statement or a declaration].
+
+ // C++ 6.8p3:
+ // The disambiguation is purely syntactic; that is, the meaning of the names
+ // occurring in such a statement, beyond whether they are type-names or not,
+ // is not generally used in or changed by the disambiguation. Class
+ // templates are instantiated as necessary to determine if a qualified name
+ // is a type-name. Disambiguation precedes parsing, and a statement
+ // disambiguated as a declaration may be an ill-formed declaration.
+
+ // We don't have to parse all of the decl-specifier-seq part. There's only
+ // an ambiguity if the first decl-specifier is
+ // simple-type-specifier/typename-specifier followed by a '(', which may
+ // indicate a function-style cast expression.
+ // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such
+ // a case.
+
+ bool InvalidAsDeclaration = false;
+ TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),
+ &InvalidAsDeclaration);
+ if (TPR != TPResult::Ambiguous())
+ return TPR != TPResult::False(); // Returns true for TPResult::True() or
+ // TPResult::Error().
+
+ // FIXME: TryParseSimpleDeclaration doesn't look past the first initializer,
+ // and so gets some cases wrong. We can't carry on if we've already seen
+ // something which makes this statement invalid as a declaration in this case,
+ // since it can cause us to misparse valid code. Revisit this once
+ // TryParseInitDeclaratorList is fixed.
+ if (InvalidAsDeclaration)
+ return false;
+
+ // FIXME: Add statistics about the number of ambiguous statements encountered
+ // and how they were resolved (number of declarations+number of expressions).
+
+ // Ok, we have a simple-type-specifier/typename-specifier followed by a '(',
+ // or an identifier which doesn't resolve as anything. We need tentative
+ // parsing...
+
+ TentativeParsingAction PA(*this);
+ TPR = TryParseSimpleDeclaration(AllowForRangeDecl);
+ PA.Revert();
+
+ // In case of an error, let the declaration parsing code handle it.
+ if (TPR == TPResult::Error())
+ return true;
+
+ // Declarations take precedence over expressions.
+ if (TPR == TPResult::Ambiguous())
+ TPR = TPResult::True();
+
+ assert(TPR == TPResult::True() || TPR == TPResult::False());
+ return TPR == TPResult::True();
+}
+
+/// simple-declaration:
+/// decl-specifier-seq init-declarator-list[opt] ';'
+///
+/// (if AllowForRangeDecl specified)
+/// for ( for-range-declaration : for-range-initializer ) statement
+/// for-range-declaration:
+/// attribute-specifier-seqopt type-specifier-seq declarator
+///
+Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
+ if (Tok.is(tok::kw_typeof))
+ TryParseTypeofSpecifier();
+ else {
+ if (Tok.is(tok::annot_cxxscope))
+ ConsumeToken();
+ ConsumeToken();
+
+ if (getLangOpts().ObjC1 && Tok.is(tok::less))
+ TryParseProtocolQualifiers();
+ }
+
+ // Two decl-specifiers in a row conclusively disambiguate this as being a
+ // simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the
+ // overwhelmingly common case that the next token is a '('.
+ if (Tok.isNot(tok::l_paren)) {
+ TPResult TPR = isCXXDeclarationSpecifier();
+ if (TPR == TPResult::Ambiguous())
+ return TPResult::True();
+ if (TPR == TPResult::True() || TPR == TPResult::Error())
+ return TPR;
+ assert(TPR == TPResult::False());
+ }
+
+ TPResult TPR = TryParseInitDeclaratorList();
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+
+ if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon)))
+ return TPResult::False();
+
+ return TPResult::Ambiguous();
+}
+
+/// init-declarator-list:
+/// init-declarator
+/// init-declarator-list ',' init-declarator
+///
+/// init-declarator:
+/// declarator initializer[opt]
+/// [GNU] declarator simple-asm-expr[opt] attributes[opt] initializer[opt]
+///
+/// initializer:
+/// '=' initializer-clause
+/// '(' expression-list ')'
+///
+/// initializer-clause:
+/// assignment-expression
+/// '{' initializer-list ','[opt] '}'
+/// '{' '}'
+///
+Parser::TPResult Parser::TryParseInitDeclaratorList() {
+ while (1) {
+ // declarator
+ TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+
+ // [GNU] simple-asm-expr[opt] attributes[opt]
+ if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+ return TPResult::True();
+
+ // initializer[opt]
+ if (Tok.is(tok::l_paren)) {
+ // Parse through the parens.
+ ConsumeParen();
+ if (!SkipUntil(tok::r_paren))
+ return TPResult::Error();
+ } else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
+ // MSVC and g++ won't examine the rest of declarators if '=' is
+ // encountered; they just conclude that we have a declaration.
+ // EDG parses the initializer completely, which is the proper behavior
+ // for this case.
+ //
+ // At present, Clang follows MSVC and g++, since the parser does not have
+ // the ability to parse an expression fully without recording the
+ // results of that parse.
+ // Also allow 'in' after on objective-c declaration as in:
+ // for (int (^b)(void) in array). Ideally this should be done in the
+ // context of parsing for-init-statement of a foreach statement only. But,
+ // in any other context 'in' is invalid after a declaration and parser
+ // issues the error regardless of outcome of this decision.
+ // FIXME. Change if above assumption does not hold.
+ return TPResult::True();
+ }
+
+ if (Tok.isNot(tok::comma))
+ break;
+ ConsumeToken(); // the comma.
+ }
+
+ return TPResult::Ambiguous();
+}
+
+/// isCXXConditionDeclaration - Disambiguates between a declaration or an
+/// expression for a condition of a if/switch/while/for statement.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+///
+/// condition:
+/// expression
+/// type-specifier-seq declarator '=' assignment-expression
+/// [C++11] type-specifier-seq declarator '=' initializer-clause
+/// [C++11] type-specifier-seq declarator braced-init-list
+/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
+/// '=' assignment-expression
+///
+bool Parser::isCXXConditionDeclaration() {
+ TPResult TPR = isCXXDeclarationSpecifier();
+ if (TPR != TPResult::Ambiguous())
+ return TPR != TPResult::False(); // Returns true for TPResult::True() or
+ // TPResult::Error().
+
+ // FIXME: Add statistics about the number of ambiguous statements encountered
+ // and how they were resolved (number of declarations+number of expressions).
+
+ // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
+ // We need tentative parsing...
+
+ TentativeParsingAction PA(*this);
+
+ // type-specifier-seq
+ if (Tok.is(tok::kw_typeof))
+ TryParseTypeofSpecifier();
+ else {
+ ConsumeToken();
+
+ if (getLangOpts().ObjC1 && Tok.is(tok::less))
+ TryParseProtocolQualifiers();
+ }
+ assert(Tok.is(tok::l_paren) && "Expected '('");
+
+ // declarator
+ TPR = TryParseDeclarator(false/*mayBeAbstract*/);
+
+ // In case of an error, let the declaration parsing code handle it.
+ if (TPR == TPResult::Error())
+ TPR = TPResult::True();
+
+ if (TPR == TPResult::Ambiguous()) {
+ // '='
+ // [GNU] simple-asm-expr[opt] attributes[opt]
+ if (Tok.is(tok::equal) ||
+ Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+ TPR = TPResult::True();
+ else if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace))
+ TPR = TPResult::True();
+ else
+ TPR = TPResult::False();
+ }
+
+ PA.Revert();
+
+ assert(TPR == TPResult::True() || TPR == TPResult::False());
+ return TPR == TPResult::True();
+}
+
+ /// \brief Determine whether the next set of tokens contains a type-id.
+ ///
+ /// The context parameter states what context we're parsing right
+ /// now, which affects how this routine copes with the token
+ /// following the type-id. If the context is TypeIdInParens, we have
+ /// already parsed the '(' and we will cease lookahead when we hit
+ /// the corresponding ')'. If the context is
+ /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
+ /// before this template argument, and will cease lookahead when we
+ /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id
+ /// and false for an expression. If during the disambiguation
+ /// process a parsing error is encountered, the function returns
+ /// true to let the declaration parsing code handle it.
+ ///
+ /// type-id:
+ /// type-specifier-seq abstract-declarator[opt]
+ ///
+bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
+
+ isAmbiguous = false;
+
+ // C++ 8.2p2:
+ // The ambiguity arising from the similarity between a function-style cast and
+ // a type-id can occur in different contexts. The ambiguity appears as a
+ // choice between a function-style cast expression and a declaration of a
+ // type. The resolution is that any construct that could possibly be a type-id
+ // in its syntactic context shall be considered a type-id.
+
+ TPResult TPR = isCXXDeclarationSpecifier();
+ if (TPR != TPResult::Ambiguous())
+ return TPR != TPResult::False(); // Returns true for TPResult::True() or
+ // TPResult::Error().
+
+ // FIXME: Add statistics about the number of ambiguous statements encountered
+ // and how they were resolved (number of declarations+number of expressions).
+
+ // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
+ // We need tentative parsing...
+
+ TentativeParsingAction PA(*this);
+
+ // type-specifier-seq
+ if (Tok.is(tok::kw_typeof))
+ TryParseTypeofSpecifier();
+ else {
+ ConsumeToken();
+
+ if (getLangOpts().ObjC1 && Tok.is(tok::less))
+ TryParseProtocolQualifiers();
+ }
+
+ assert(Tok.is(tok::l_paren) && "Expected '('");
+
+ // declarator
+ TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
+
+ // In case of an error, let the declaration parsing code handle it.
+ if (TPR == TPResult::Error())
+ TPR = TPResult::True();
+
+ if (TPR == TPResult::Ambiguous()) {
+ // We are supposed to be inside parens, so if after the abstract declarator
+ // we encounter a ')' this is a type-id, otherwise it's an expression.
+ if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
+ TPR = TPResult::True();
+ isAmbiguous = true;
+
+ // We are supposed to be inside a template argument, so if after
+ // the abstract declarator we encounter a '>', '>>' (in C++0x), or
+ // ',', this is a type-id. Otherwise, it's an expression.
+ } else if (Context == TypeIdAsTemplateArgument &&
+ (Tok.is(tok::greater) || Tok.is(tok::comma) ||
+ (getLangOpts().CPlusPlus0x && Tok.is(tok::greatergreater)))) {
+ TPR = TPResult::True();
+ isAmbiguous = true;
+
+ } else
+ TPR = TPResult::False();
+ }
+
+ PA.Revert();
+
+ assert(TPR == TPResult::True() || TPR == TPResult::False());
+ return TPR == TPResult::True();
+}
+
+/// \brief Returns true if this is a C++11 attribute-specifier. Per
+/// C++11 [dcl.attr.grammar]p6, two consecutive left square bracket tokens
+/// always introduce an attribute. In Objective-C++11, this rule does not
+/// apply if either '[' begins a message-send.
+///
+/// If Disambiguate is true, we try harder to determine whether a '[[' starts
+/// an attribute-specifier, and return CAK_InvalidAttributeSpecifier if not.
+///
+/// If OuterMightBeMessageSend is true, we assume the outer '[' is either an
+/// Obj-C message send or the start of an attribute. Otherwise, we assume it
+/// is not an Obj-C message send.
+///
+/// C++11 [dcl.attr.grammar]:
+///
+/// attribute-specifier:
+/// '[' '[' attribute-list ']' ']'
+/// alignment-specifier
+///
+/// attribute-list:
+/// attribute[opt]
+/// attribute-list ',' attribute[opt]
+/// attribute '...'
+/// attribute-list ',' attribute '...'
+///
+/// attribute:
+/// attribute-token attribute-argument-clause[opt]
+///
+/// attribute-token:
+/// identifier
+/// identifier '::' identifier
+///
+/// attribute-argument-clause:
+/// '(' balanced-token-seq ')'
+Parser::CXX11AttributeKind
+Parser::isCXX11AttributeSpecifier(bool Disambiguate,
+ bool OuterMightBeMessageSend) {
+ if (Tok.is(tok::kw_alignas))
+ return CAK_AttributeSpecifier;
+
+ if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
+ return CAK_NotAttributeSpecifier;
+
+ // No tentative parsing if we don't need to look for ']]' or a lambda.
+ if (!Disambiguate && !getLangOpts().ObjC1)
+ return CAK_AttributeSpecifier;
+
+ TentativeParsingAction PA(*this);
+
+ // Opening brackets were checked for above.
+ ConsumeBracket();
+
+ // Outside Obj-C++11, treat anything with a matching ']]' as an attribute.
+ if (!getLangOpts().ObjC1) {
+ ConsumeBracket();
+
+ bool IsAttribute = SkipUntil(tok::r_square, false);
+ IsAttribute &= Tok.is(tok::r_square);
+
+ PA.Revert();
+
+ return IsAttribute ? CAK_AttributeSpecifier : CAK_InvalidAttributeSpecifier;
+ }
+
+ // In Obj-C++11, we need to distinguish four situations:
+ // 1a) int x[[attr]]; C++11 attribute.
+ // 1b) [[attr]]; C++11 statement attribute.
+ // 2) int x[[obj](){ return 1; }()]; Lambda in array size/index.
+ // 3a) int x[[obj get]]; Message send in array size/index.
+ // 3b) [[Class alloc] init]; Message send in message send.
+ // 4) [[obj]{ return self; }() doStuff]; Lambda in message send.
+ // (1) is an attribute, (2) is ill-formed, and (3) and (4) are accepted.
+
+ // If we have a lambda-introducer, then this is definitely not a message send.
+ // FIXME: If this disambiguation is too slow, fold the tentative lambda parse
+ // into the tentative attribute parse below.
+ LambdaIntroducer Intro;
+ if (!TryParseLambdaIntroducer(Intro)) {
+ // A lambda cannot end with ']]', and an attribute must.
+ bool IsAttribute = Tok.is(tok::r_square);
+
+ PA.Revert();
+
+ if (IsAttribute)
+ // Case 1: C++11 attribute.
+ return CAK_AttributeSpecifier;
+
+ if (OuterMightBeMessageSend)
+ // Case 4: Lambda in message send.
+ return CAK_NotAttributeSpecifier;
+
+ // Case 2: Lambda in array size / index.
+ return CAK_InvalidAttributeSpecifier;
+ }
+
+ ConsumeBracket();
+
+ // If we don't have a lambda-introducer, then we have an attribute or a
+ // message-send.
+ bool IsAttribute = true;
+ while (Tok.isNot(tok::r_square)) {
+ if (Tok.is(tok::comma)) {
+ // Case 1: Stray commas can only occur in attributes.
+ PA.Revert();
+ return CAK_AttributeSpecifier;
+ }
+
+ // Parse the attribute-token, if present.
+ // C++11 [dcl.attr.grammar]:
+ // If a keyword or an alternative token that satisfies the syntactic
+ // requirements of an identifier is contained in an attribute-token,
+ // it is considered an identifier.
+ SourceLocation Loc;
+ if (!TryParseCXX11AttributeIdentifier(Loc)) {
+ IsAttribute = false;
+ break;
+ }
+ if (Tok.is(tok::coloncolon)) {
+ ConsumeToken();
+ if (!TryParseCXX11AttributeIdentifier(Loc)) {
+ IsAttribute = false;
+ break;
+ }
+ }
+
+ // Parse the attribute-argument-clause, if present.
+ if (Tok.is(tok::l_paren)) {
+ ConsumeParen();
+ if (!SkipUntil(tok::r_paren, false)) {
+ IsAttribute = false;
+ break;
+ }
+ }
+
+ if (Tok.is(tok::ellipsis))
+ ConsumeToken();
+
+ if (Tok.isNot(tok::comma))
+ break;
+
+ ConsumeToken();
+ }
+
+ // An attribute must end ']]'.
+ if (IsAttribute) {
+ if (Tok.is(tok::r_square)) {
+ ConsumeBracket();
+ IsAttribute = Tok.is(tok::r_square);
+ } else {
+ IsAttribute = false;
+ }
+ }
+
+ PA.Revert();
+
+ if (IsAttribute)
+ // Case 1: C++11 statement attribute.
+ return CAK_AttributeSpecifier;
+
+ // Case 3: Message send.
+ return CAK_NotAttributeSpecifier;
+}
+
+/// declarator:
+/// direct-declarator
+/// ptr-operator declarator
+///
+/// direct-declarator:
+/// declarator-id
+/// direct-declarator '(' parameter-declaration-clause ')'
+/// cv-qualifier-seq[opt] exception-specification[opt]
+/// direct-declarator '[' constant-expression[opt] ']'
+/// '(' declarator ')'
+/// [GNU] '(' attributes declarator ')'
+///
+/// abstract-declarator:
+/// ptr-operator abstract-declarator[opt]
+/// direct-abstract-declarator
+/// ...
+///
+/// direct-abstract-declarator:
+/// direct-abstract-declarator[opt]
+/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+/// exception-specification[opt]
+/// direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
+/// '(' abstract-declarator ')'
+///
+/// ptr-operator:
+/// '*' cv-qualifier-seq[opt]
+/// '&'
+/// [C++0x] '&&' [TODO]
+/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
+///
+/// cv-qualifier-seq:
+/// cv-qualifier cv-qualifier-seq[opt]
+///
+/// cv-qualifier:
+/// 'const'
+/// 'volatile'
+///
+/// declarator-id:
+/// '...'[opt] id-expression
+///
+/// id-expression:
+/// unqualified-id
+/// qualified-id [TODO]
+///
+/// unqualified-id:
+/// identifier
+/// operator-function-id [TODO]
+/// conversion-function-id [TODO]
+/// '~' class-name [TODO]
+/// template-id [TODO]
+///
+Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
+ bool mayHaveIdentifier) {
+ // declarator:
+ // direct-declarator
+ // ptr-operator declarator
+
+ while (1) {
+ if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
+ if (TryAnnotateCXXScopeToken(true))
+ return TPResult::Error();
+
+ if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
+ Tok.is(tok::ampamp) ||
+ (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
+ // ptr-operator
+ ConsumeToken();
+ while (Tok.is(tok::kw_const) ||
+ Tok.is(tok::kw_volatile) ||
+ Tok.is(tok::kw_restrict))
+ ConsumeToken();
+ } else {
+ break;
+ }
+ }
+
+ // direct-declarator:
+ // direct-abstract-declarator:
+ if (Tok.is(tok::ellipsis))
+ ConsumeToken();
+
+ if ((Tok.is(tok::identifier) ||
+ (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) &&
+ mayHaveIdentifier) {
+ // declarator-id
+ if (Tok.is(tok::annot_cxxscope))
+ ConsumeToken();
+ else
+ TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo());
+ ConsumeToken();
+ } else if (Tok.is(tok::l_paren)) {
+ ConsumeParen();
+ if (mayBeAbstract &&
+ (Tok.is(tok::r_paren) || // 'int()' is a function.
+ // 'int(...)' is a function.
+ (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren)) ||
+ isDeclarationSpecifier())) { // 'int(int)' is a function.
+ // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+ // exception-specification[opt]
+ TPResult TPR = TryParseFunctionDeclarator();
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+ } else {
+ // '(' declarator ')'
+ // '(' attributes declarator ')'
+ // '(' abstract-declarator ')'
+ if (Tok.is(tok::kw___attribute) ||
+ Tok.is(tok::kw___declspec) ||
+ Tok.is(tok::kw___cdecl) ||
+ Tok.is(tok::kw___stdcall) ||
+ Tok.is(tok::kw___fastcall) ||
+ Tok.is(tok::kw___thiscall) ||
+ Tok.is(tok::kw___unaligned))
+ return TPResult::True(); // attributes indicate declaration
+ TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+ if (Tok.isNot(tok::r_paren))
+ return TPResult::False();
+ ConsumeParen();
+ }
+ } else if (!mayBeAbstract) {
+ return TPResult::False();
+ }
+
+ while (1) {
+ TPResult TPR(TPResult::Ambiguous());
+
+ // abstract-declarator: ...
+ if (Tok.is(tok::ellipsis))
+ ConsumeToken();
+
+ if (Tok.is(tok::l_paren)) {
+ // Check whether we have a function declarator or a possible ctor-style
+ // initializer that follows the declarator. Note that ctor-style
+ // initializers are not possible in contexts where abstract declarators
+ // are allowed.
+ if (!mayBeAbstract && !isCXXFunctionDeclarator())
+ break;
+
+ // direct-declarator '(' parameter-declaration-clause ')'
+ // cv-qualifier-seq[opt] exception-specification[opt]
+ ConsumeParen();
+ TPR = TryParseFunctionDeclarator();
+ } else if (Tok.is(tok::l_square)) {
+ // direct-declarator '[' constant-expression[opt] ']'
+ // direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
+ TPR = TryParseBracketDeclarator();
+ } else {
+ break;
+ }
+
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+ }
+
+ return TPResult::Ambiguous();
+}
+
+Parser::TPResult
+Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
+ switch (Kind) {
+ // Obviously starts an expression.
+ case tok::numeric_constant:
+ case tok::char_constant:
+ case tok::wide_char_constant:
+ case tok::utf16_char_constant:
+ case tok::utf32_char_constant:
+ case tok::string_literal:
+ case tok::wide_string_literal:
+ case tok::utf8_string_literal:
+ case tok::utf16_string_literal:
+ case tok::utf32_string_literal:
+ case tok::l_square:
+ case tok::l_paren:
+ case tok::amp:
+ case tok::ampamp:
+ case tok::star:
+ case tok::plus:
+ case tok::plusplus:
+ case tok::minus:
+ case tok::minusminus:
+ case tok::tilde:
+ case tok::exclaim:
+ case tok::kw_sizeof:
+ case tok::kw___func__:
+ case tok::kw_const_cast:
+ case tok::kw_delete:
+ case tok::kw_dynamic_cast:
+ case tok::kw_false:
+ case tok::kw_new:
+ case tok::kw_operator:
+ case tok::kw_reinterpret_cast:
+ case tok::kw_static_cast:
+ case tok::kw_this:
+ case tok::kw_throw:
+ case tok::kw_true:
+ case tok::kw_typeid:
+ case tok::kw_alignof:
+ case tok::kw_noexcept:
+ case tok::kw_nullptr:
+ case tok::kw__Alignof:
+ case tok::kw___null:
+ case tok::kw___alignof:
+ case tok::kw___builtin_choose_expr:
+ case tok::kw___builtin_offsetof:
+ case tok::kw___builtin_types_compatible_p:
+ case tok::kw___builtin_va_arg:
+ case tok::kw___imag:
+ case tok::kw___real:
+ case tok::kw___FUNCTION__:
+ case tok::kw_L__FUNCTION__:
+ case tok::kw___PRETTY_FUNCTION__:
+ case tok::kw___has_nothrow_assign:
+ case tok::kw___has_nothrow_copy:
+ case tok::kw___has_nothrow_constructor:
+ case tok::kw___has_trivial_assign:
+ case tok::kw___has_trivial_copy:
+ case tok::kw___has_trivial_constructor:
+ case tok::kw___has_trivial_destructor:
+ case tok::kw___has_virtual_destructor:
+ case tok::kw___is_abstract:
+ case tok::kw___is_base_of:
+ case tok::kw___is_class:
+ case tok::kw___is_convertible_to:
+ case tok::kw___is_empty:
+ case tok::kw___is_enum:
+ case tok::kw___is_interface_class:
+ case tok::kw___is_final:
+ case tok::kw___is_literal:
+ case tok::kw___is_literal_type:
+ case tok::kw___is_pod:
+ case tok::kw___is_polymorphic:
+ case tok::kw___is_trivial:
+ case tok::kw___is_trivially_assignable:
+ case tok::kw___is_trivially_constructible:
+ case tok::kw___is_trivially_copyable:
+ case tok::kw___is_union:
+ case tok::kw___uuidof:
+ return TPResult::True();
+
+ // Obviously starts a type-specifier-seq:
+ case tok::kw_char:
+ case tok::kw_const:
+ case tok::kw_double:
+ case tok::kw_enum:
+ case tok::kw_half:
+ case tok::kw_float:
+ case tok::kw_int:
+ case tok::kw_long:
+ case tok::kw___int64:
+ case tok::kw___int128:
+ case tok::kw_restrict:
+ case tok::kw_short:
+ case tok::kw_signed:
+ case tok::kw_struct:
+ case tok::kw_union:
+ case tok::kw_unsigned:
+ case tok::kw_void:
+ case tok::kw_volatile:
+ case tok::kw__Bool:
+ case tok::kw__Complex:
+ case tok::kw_class:
+ case tok::kw_typename:
+ case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
+ case tok::kw___underlying_type:
+ case tok::kw_thread_local:
+ case tok::kw__Decimal32:
+ case tok::kw__Decimal64:
+ case tok::kw__Decimal128:
+ case tok::kw___thread:
+ case tok::kw_typeof:
+ case tok::kw___cdecl:
+ case tok::kw___stdcall:
+ case tok::kw___fastcall:
+ case tok::kw___thiscall:
+ case tok::kw___unaligned:
+ case tok::kw___vector:
+ case tok::kw___pixel:
+ case tok::kw__Atomic:
+ case tok::kw___unknown_anytype:
+ return TPResult::False();
+
+ default:
+ break;
+ }
+
+ return TPResult::Ambiguous();
+}
+
+bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
+ return std::find(TentativelyDeclaredIdentifiers.begin(),
+ TentativelyDeclaredIdentifiers.end(), II)
+ != TentativelyDeclaredIdentifiers.end();
+}
+
+/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration
+/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could
+/// be either a decl-specifier or a function-style cast, and TPResult::Error()
+/// if a parsing error was found and reported.
+///
+/// If HasMissingTypename is provided, a name with a dependent scope specifier
+/// will be treated as ambiguous if the 'typename' keyword is missing. If this
+/// happens, *HasMissingTypename will be set to 'true'. This will also be used
+/// as an indicator that undeclared identifiers (which will trigger a later
+/// parse error) should be treated as types. Returns TPResult::Ambiguous() in
+/// such cases.
+///
+/// decl-specifier:
+/// storage-class-specifier
+/// type-specifier
+/// function-specifier
+/// 'friend'
+/// 'typedef'
+/// [C++0x] 'constexpr'
+/// [GNU] attributes declaration-specifiers[opt]
+///
+/// storage-class-specifier:
+/// 'register'
+/// 'static'
+/// 'extern'
+/// 'mutable'
+/// 'auto'
+/// [GNU] '__thread'
+///
+/// function-specifier:
+/// 'inline'
+/// 'virtual'
+/// 'explicit'
+///
+/// typedef-name:
+/// identifier
+///
+/// type-specifier:
+/// simple-type-specifier
+/// class-specifier
+/// enum-specifier
+/// elaborated-type-specifier
+/// typename-specifier
+/// cv-qualifier
+///
+/// simple-type-specifier:
+/// '::'[opt] nested-name-specifier[opt] type-name
+/// '::'[opt] nested-name-specifier 'template'
+/// simple-template-id [TODO]
+/// 'char'
+/// 'wchar_t'
+/// 'bool'
+/// 'short'
+/// 'int'
+/// 'long'
+/// 'signed'
+/// 'unsigned'
+/// 'float'
+/// 'double'
+/// 'void'
+/// [GNU] typeof-specifier
+/// [GNU] '_Complex'
+/// [C++0x] 'auto' [TODO]
+/// [C++0x] 'decltype' ( expression )
+///
+/// type-name:
+/// class-name
+/// enum-name
+/// typedef-name
+///
+/// elaborated-type-specifier:
+/// class-key '::'[opt] nested-name-specifier[opt] identifier
+/// class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]
+/// simple-template-id
+/// 'enum' '::'[opt] nested-name-specifier[opt] identifier
+///
+/// enum-name:
+/// identifier
+///
+/// enum-specifier:
+/// 'enum' identifier[opt] '{' enumerator-list[opt] '}'
+/// 'enum' identifier[opt] '{' enumerator-list ',' '}'
+///
+/// class-specifier:
+/// class-head '{' member-specification[opt] '}'
+///
+/// class-head:
+/// class-key identifier[opt] base-clause[opt]
+/// class-key nested-name-specifier identifier base-clause[opt]
+/// class-key nested-name-specifier[opt] simple-template-id
+/// base-clause[opt]
+///
+/// class-key:
+/// 'class'
+/// 'struct'
+/// 'union'
+///
+/// cv-qualifier:
+/// 'const'
+/// 'volatile'
+/// [GNU] restrict
+///
+Parser::TPResult
+Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
+ bool *HasMissingTypename) {
+ switch (Tok.getKind()) {
+ case tok::identifier: {
+ // Check for need to substitute AltiVec __vector keyword
+ // for "vector" identifier.
+ if (TryAltiVecVectorToken())
+ return TPResult::True();
+
+ const Token &Next = NextToken();
+ // In 'foo bar', 'foo' is always a type name outside of Objective-C.
+ if (!getLangOpts().ObjC1 && Next.is(tok::identifier))
+ return TPResult::True();
+
+ if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) {
+ // Determine whether this is a valid expression. If not, we will hit
+ // a parse error one way or another. In that case, tell the caller that
+ // this is ambiguous. Typo-correct to type and expression keywords and
+ // to types and identifiers, in order to try to recover from errors.
+ CorrectionCandidateCallback TypoCorrection;
+ TypoCorrection.WantRemainingKeywords = false;
+ switch (TryAnnotateName(false /* no nested name specifier */,
+ &TypoCorrection)) {
+ case ANK_Error:
+ return TPResult::Error();
+ case ANK_TentativeDecl:
+ return TPResult::False();
+ case ANK_TemplateName:
+ // A bare type template-name which can't be a template template
+ // argument is an error, and was probably intended to be a type.
+ return GreaterThanIsOperator ? TPResult::True() : TPResult::False();
+ case ANK_Unresolved:
+ return HasMissingTypename ? TPResult::Ambiguous() : TPResult::False();
+ case ANK_Success:
+ break;
+ }
+ assert(Tok.isNot(tok::identifier) &&
+ "TryAnnotateName succeeded without producing an annotation");
+ } else {
+ // This might possibly be a type with a dependent scope specifier and
+ // a missing 'typename' keyword. Don't use TryAnnotateName in this case,
+ // since it will annotate as a primary expression, and we want to use the
+ // "missing 'typename'" logic.
+ if (TryAnnotateTypeOrScopeToken())
+ return TPResult::Error();
+ // If annotation failed, assume it's a non-type.
+ // FIXME: If this happens due to an undeclared identifier, treat it as
+ // ambiguous.
+ if (Tok.is(tok::identifier))
+ return TPResult::False();
+ }
+
+ // We annotated this token as something. Recurse to handle whatever we got.
+ return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
+ }
+
+ case tok::kw_typename: // typename T::type
+ // Annotate typenames and C++ scope specifiers. If we get one, just
+ // recurse to handle whatever we get.
+ if (TryAnnotateTypeOrScopeToken())
+ return TPResult::Error();
+ return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
+
+ case tok::coloncolon: { // ::foo::bar
+ const Token &Next = NextToken();
+ if (Next.is(tok::kw_new) || // ::new
+ Next.is(tok::kw_delete)) // ::delete
+ return TPResult::False();
+ }
+ // Fall through.
+ case tok::kw_decltype:
+ // Annotate typenames and C++ scope specifiers. If we get one, just
+ // recurse to handle whatever we get.
+ if (TryAnnotateTypeOrScopeToken())
+ return TPResult::Error();
+ return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
+
+ // decl-specifier:
+ // storage-class-specifier
+ // type-specifier
+ // function-specifier
+ // 'friend'
+ // 'typedef'
+ // 'constexpr'
+ case tok::kw_friend:
+ case tok::kw_typedef:
+ case tok::kw_constexpr:
+ // storage-class-specifier
+ case tok::kw_register:
+ case tok::kw_static:
+ case tok::kw_extern:
+ case tok::kw_mutable:
+ case tok::kw_auto:
+ case tok::kw___thread:
+ // function-specifier
+ case tok::kw_inline:
+ case tok::kw_virtual:
+ case tok::kw_explicit:
+
+ // Modules
+ case tok::kw___module_private__:
+
+ // Debugger support
+ case tok::kw___unknown_anytype:
+
+ // type-specifier:
+ // simple-type-specifier
+ // class-specifier
+ // enum-specifier
+ // elaborated-type-specifier
+ // typename-specifier
+ // cv-qualifier
+
+ // class-specifier
+ // elaborated-type-specifier
+ case tok::kw_class:
+ case tok::kw_struct:
+ case tok::kw_union:
+ // enum-specifier
+ case tok::kw_enum:
+ // cv-qualifier
+ case tok::kw_const:
+ case tok::kw_volatile:
+
+ // GNU
+ case tok::kw_restrict:
+ case tok::kw__Complex:
+ case tok::kw___attribute:
+ return TPResult::True();
+
+ // Microsoft
+ case tok::kw___declspec:
+ case tok::kw___cdecl:
+ case tok::kw___stdcall:
+ case tok::kw___fastcall:
+ case tok::kw___thiscall:
+ case tok::kw___w64:
+ case tok::kw___ptr64:
+ case tok::kw___ptr32:
+ case tok::kw___forceinline:
+ case tok::kw___unaligned:
+ return TPResult::True();
+
+ // Borland
+ case tok::kw___pascal:
+ return TPResult::True();
+
+ // AltiVec
+ case tok::kw___vector:
+ return TPResult::True();
+
+ case tok::annot_template_id: {
+ TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
+ if (TemplateId->Kind != TNK_Type_template)
+ return TPResult::False();
+ CXXScopeSpec SS;
+ AnnotateTemplateIdTokenAsType();
+ assert(Tok.is(tok::annot_typename));
+ goto case_typename;
+ }
+
+ case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
+ // We've already annotated a scope; try to annotate a type.
+ if (TryAnnotateTypeOrScopeToken())
+ return TPResult::Error();
+ if (!Tok.is(tok::annot_typename)) {
+ // If the next token is an identifier or a type qualifier, then this
+ // can't possibly be a valid expression either.
+ if (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier)) {
+ CXXScopeSpec SS;
+ Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
+ Tok.getAnnotationRange(),
+ SS);
+ if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) {
+ TentativeParsingAction PA(*this);
+ ConsumeToken();
+ ConsumeToken();
+ bool isIdentifier = Tok.is(tok::identifier);
+ TPResult TPR = TPResult::False();
+ if (!isIdentifier)
+ TPR = isCXXDeclarationSpecifier(BracedCastResult,
+ HasMissingTypename);
+ PA.Revert();
+
+ if (isIdentifier ||
+ TPR == TPResult::True() || TPR == TPResult::Error())
+ return TPResult::Error();
+
+ if (HasMissingTypename) {
+ // We can't tell whether this is a missing 'typename' or a valid
+ // expression.
+ *HasMissingTypename = true;
+ return TPResult::Ambiguous();
+ }
+ } else {
+ // Try to resolve the name. If it doesn't exist, assume it was
+ // intended to name a type and keep disambiguating.
+ switch (TryAnnotateName(false /* SS is not dependent */)) {
+ case ANK_Error:
+ return TPResult::Error();
+ case ANK_TentativeDecl:
+ return TPResult::False();
+ case ANK_TemplateName:
+ // A bare type template-name which can't be a template template
+ // argument is an error, and was probably intended to be a type.
+ return GreaterThanIsOperator ? TPResult::True() : TPResult::False();
+ case ANK_Unresolved:
+ return HasMissingTypename ? TPResult::Ambiguous()
+ : TPResult::False();
+ case ANK_Success:
+ // Annotated it, check again.
+ assert(Tok.isNot(tok::annot_cxxscope) ||
+ NextToken().isNot(tok::identifier));
+ return isCXXDeclarationSpecifier(BracedCastResult,
+ HasMissingTypename);
+ }
+ }
+ }
+ return TPResult::False();
+ }
+ // If that succeeded, fallthrough into the generic simple-type-id case.
+
+ // The ambiguity resides in a simple-type-specifier/typename-specifier
+ // followed by a '('. The '(' could either be the start of:
+ //
+ // direct-declarator:
+ // '(' declarator ')'
+ //
+ // direct-abstract-declarator:
+ // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+ // exception-specification[opt]
+ // '(' abstract-declarator ')'
+ //
+ // or part of a function-style cast expression:
+ //
+ // simple-type-specifier '(' expression-list[opt] ')'
+ //
+
+ // simple-type-specifier:
+
+ case tok::annot_typename:
+ case_typename:
+ // In Objective-C, we might have a protocol-qualified type.
+ if (getLangOpts().ObjC1 && NextToken().is(tok::less)) {
+ // Tentatively parse the
+ TentativeParsingAction PA(*this);
+ ConsumeToken(); // The type token
+
+ TPResult TPR = TryParseProtocolQualifiers();
+ bool isFollowedByParen = Tok.is(tok::l_paren);
+ bool isFollowedByBrace = Tok.is(tok::l_brace);
+
+ PA.Revert();
+
+ if (TPR == TPResult::Error())
+ return TPResult::Error();
+
+ if (isFollowedByParen)
+ return TPResult::Ambiguous();
+
+ if (getLangOpts().CPlusPlus0x && isFollowedByBrace)
+ return BracedCastResult;
+
+ return TPResult::True();
+ }
+
+ case tok::kw_char:
+ case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
+ case tok::kw_bool:
+ case tok::kw_short:
+ case tok::kw_int:
+ case tok::kw_long:
+ case tok::kw___int64:
+ case tok::kw___int128:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw_half:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_void:
+ case tok::annot_decltype:
+ if (NextToken().is(tok::l_paren))
+ return TPResult::Ambiguous();
+
+ // This is a function-style cast in all cases we disambiguate other than
+ // one:
+ // struct S {
+ // enum E : int { a = 4 }; // enum
+ // enum E : int { 4 }; // bit-field
+ // };
+ if (getLangOpts().CPlusPlus0x && NextToken().is(tok::l_brace))
+ return BracedCastResult;
+
+ if (isStartOfObjCClassMessageMissingOpenBracket())
+ return TPResult::False();
+
+ return TPResult::True();
+
+ // GNU typeof support.
+ case tok::kw_typeof: {
+ if (NextToken().isNot(tok::l_paren))
+ return TPResult::True();
+
+ TentativeParsingAction PA(*this);
+
+ TPResult TPR = TryParseTypeofSpecifier();
+ bool isFollowedByParen = Tok.is(tok::l_paren);
+ bool isFollowedByBrace = Tok.is(tok::l_brace);
+
+ PA.Revert();
+
+ if (TPR == TPResult::Error())
+ return TPResult::Error();
+
+ if (isFollowedByParen)
+ return TPResult::Ambiguous();
+
+ if (getLangOpts().CPlusPlus0x && isFollowedByBrace)
+ return BracedCastResult;
+
+ return TPResult::True();
+ }
+
+ // C++0x type traits support
+ case tok::kw___underlying_type:
+ return TPResult::True();
+
+ // C11 _Atomic
+ case tok::kw__Atomic:
+ return TPResult::True();
+
+ default:
+ return TPResult::False();
+ }
+}
+
+/// [GNU] typeof-specifier:
+/// 'typeof' '(' expressions ')'
+/// 'typeof' '(' type-name ')'
+///
+Parser::TPResult Parser::TryParseTypeofSpecifier() {
+ assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!");
+ ConsumeToken();
+
+ assert(Tok.is(tok::l_paren) && "Expected '('");
+ // Parse through the parens after 'typeof'.
+ ConsumeParen();
+ if (!SkipUntil(tok::r_paren))
+ return TPResult::Error();
+
+ return TPResult::Ambiguous();
+}
+
+/// [ObjC] protocol-qualifiers:
+//// '<' identifier-list '>'
+Parser::TPResult Parser::TryParseProtocolQualifiers() {
+ assert(Tok.is(tok::less) && "Expected '<' for qualifier list");
+ ConsumeToken();
+ do {
+ if (Tok.isNot(tok::identifier))
+ return TPResult::Error();
+ ConsumeToken();
+
+ if (Tok.is(tok::comma)) {
+ ConsumeToken();
+ continue;
+ }
+
+ if (Tok.is(tok::greater)) {
+ ConsumeToken();
+ return TPResult::Ambiguous();
+ }
+ } while (false);
+
+ return TPResult::Error();
+}
+
+Parser::TPResult
+Parser::TryParseDeclarationSpecifier(bool *HasMissingTypename) {
+ TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(),
+ HasMissingTypename);
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+
+ if (Tok.is(tok::kw_typeof))
+ TryParseTypeofSpecifier();
+ else {
+ if (Tok.is(tok::annot_cxxscope))
+ ConsumeToken();
+ ConsumeToken();
+
+ if (getLangOpts().ObjC1 && Tok.is(tok::less))
+ TryParseProtocolQualifiers();
+ }
+
+ return TPResult::Ambiguous();
+}
+
+/// isCXXFunctionDeclarator - Disambiguates between a function declarator or
+/// a constructor-style initializer, when parsing declaration statements.
+/// Returns true for function declarator and false for constructor-style
+/// initializer.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+///
+/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+/// exception-specification[opt]
+///
+bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) {
+
+ // C++ 8.2p1:
+ // The ambiguity arising from the similarity between a function-style cast and
+ // a declaration mentioned in 6.8 can also occur in the context of a
+ // declaration. In that context, the choice is between a function declaration
+ // with a redundant set of parentheses around a parameter name and an object
+ // declaration with a function-style cast as the initializer. Just as for the
+ // ambiguities mentioned in 6.8, the resolution is to consider any construct
+ // that could possibly be a declaration a declaration.
+
+ TentativeParsingAction PA(*this);
+
+ ConsumeParen();
+ bool InvalidAsDeclaration = false;
+ TPResult TPR = TryParseParameterDeclarationClause(&InvalidAsDeclaration);
+ if (TPR == TPResult::Ambiguous()) {
+ if (Tok.isNot(tok::r_paren))
+ TPR = TPResult::False();
+ else {
+ const Token &Next = NextToken();
+ if (Next.is(tok::amp) || Next.is(tok::ampamp) ||
+ Next.is(tok::kw_const) || Next.is(tok::kw_volatile) ||
+ Next.is(tok::kw_throw) || Next.is(tok::kw_noexcept) ||
+ Next.is(tok::l_square) || isCXX0XVirtSpecifier(Next) ||
+ Next.is(tok::l_brace) || Next.is(tok::kw_try) ||
+ Next.is(tok::equal) || Next.is(tok::arrow))
+ // The next token cannot appear after a constructor-style initializer,
+ // and can appear next in a function definition. This must be a function
+ // declarator.
+ TPR = TPResult::True();
+ else if (InvalidAsDeclaration)
+ // Use the absence of 'typename' as a tie-breaker.
+ TPR = TPResult::False();
+ }
+ }
+
+ PA.Revert();
+
+ if (IsAmbiguous && TPR == TPResult::Ambiguous())
+ *IsAmbiguous = true;
+
+ // In case of an error, let the declaration parsing code handle it.
+ return TPR != TPResult::False();
+}
+
+/// parameter-declaration-clause:
+/// parameter-declaration-list[opt] '...'[opt]
+/// parameter-declaration-list ',' '...'
+///
+/// parameter-declaration-list:
+/// parameter-declaration
+/// parameter-declaration-list ',' parameter-declaration
+///
+/// parameter-declaration:
+/// attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]
+/// attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]
+/// '=' assignment-expression
+/// attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]
+/// attributes[opt]
+/// attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]
+/// attributes[opt] '=' assignment-expression
+///
+Parser::TPResult
+Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration) {
+
+ if (Tok.is(tok::r_paren))
+ return TPResult::Ambiguous();
+
+ // parameter-declaration-list[opt] '...'[opt]
+ // parameter-declaration-list ',' '...'
+ //
+ // parameter-declaration-list:
+ // parameter-declaration
+ // parameter-declaration-list ',' parameter-declaration
+ //
+ while (1) {
+ // '...'[opt]
+ if (Tok.is(tok::ellipsis)) {
+ ConsumeToken();
+ if (Tok.is(tok::r_paren))
+ return TPResult::True(); // '...)' is a sign of a function declarator.
+ else
+ return TPResult::False();
+ }
+
+ // An attribute-specifier-seq here is a sign of a function declarator.
+ if (isCXX11AttributeSpecifier(/*Disambiguate*/false,
+ /*OuterMightBeMessageSend*/true))
+ return TPResult::True();
+
+ ParsedAttributes attrs(AttrFactory);
+ MaybeParseMicrosoftAttributes(attrs);
+
+ // decl-specifier-seq
+ // A parameter-declaration's initializer must be preceded by an '=', so
+ // decl-specifier-seq '{' is not a parameter in C++11.
+ TPResult TPR = TryParseDeclarationSpecifier(InvalidAsDeclaration);
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+
+ // declarator
+ // abstract-declarator[opt]
+ TPR = TryParseDeclarator(true/*mayBeAbstract*/);
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+
+ // [GNU] attributes[opt]
+ if (Tok.is(tok::kw___attribute))
+ return TPResult::True();
+
+ if (Tok.is(tok::equal)) {
+ // '=' assignment-expression
+ // Parse through assignment-expression.
+ if (!SkipUntil(tok::comma, tok::r_paren, true/*StopAtSemi*/,
+ true/*DontConsume*/))
+ return TPResult::Error();
+ }
+
+ if (Tok.is(tok::ellipsis)) {
+ ConsumeToken();
+ if (Tok.is(tok::r_paren))
+ return TPResult::True(); // '...)' is a sign of a function declarator.
+ else
+ return TPResult::False();
+ }
+
+ if (Tok.isNot(tok::comma))
+ break;
+ ConsumeToken(); // the comma.
+ }
+
+ return TPResult::Ambiguous();
+}
+
+/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
+/// parsing as a function declarator.
+/// If TryParseFunctionDeclarator fully parsed the function declarator, it will
+/// return TPResult::Ambiguous(), otherwise it will return either False() or
+/// Error().
+///
+/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+/// exception-specification[opt]
+///
+/// exception-specification:
+/// 'throw' '(' type-id-list[opt] ')'
+///
+Parser::TPResult Parser::TryParseFunctionDeclarator() {
+
+ // The '(' is already parsed.
+
+ TPResult TPR = TryParseParameterDeclarationClause();
+ if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
+ TPR = TPResult::False();
+
+ if (TPR == TPResult::False() || TPR == TPResult::Error())
+ return TPR;
+
+ // Parse through the parens.
+ if (!SkipUntil(tok::r_paren))
+ return TPResult::Error();
+
+ // cv-qualifier-seq
+ while (Tok.is(tok::kw_const) ||
+ Tok.is(tok::kw_volatile) ||
+ Tok.is(tok::kw_restrict) )
+ ConsumeToken();
+
+ // ref-qualifier[opt]
+ if (Tok.is(tok::amp) || Tok.is(tok::ampamp))
+ ConsumeToken();
+
+ // exception-specification
+ if (Tok.is(tok::kw_throw)) {
+ ConsumeToken();
+ if (Tok.isNot(tok::l_paren))
+ return TPResult::Error();
+
+ // Parse through the parens after 'throw'.
+ ConsumeParen();
+ if (!SkipUntil(tok::r_paren))
+ return TPResult::Error();
+ }
+ if (Tok.is(tok::kw_noexcept)) {
+ ConsumeToken();
+ // Possibly an expression as well.
+ if (Tok.is(tok::l_paren)) {
+ // Find the matching rparen.
+ ConsumeParen();
+ if (!SkipUntil(tok::r_paren))
+ return TPResult::Error();
+ }
+ }
+
+ return TPResult::Ambiguous();
+}
+
+/// '[' constant-expression[opt] ']'
+///
+Parser::TPResult Parser::TryParseBracketDeclarator() {
+ ConsumeBracket();
+ if (!SkipUntil(tok::r_square))
+ return TPResult::Error();
+
+ return TPResult::Ambiguous();
+}
case TST_unspecified:
case TST_void:
case TST_wchar:
- case TST_image1d_t:
- case TST_image1d_array_t:
- case TST_image1d_buffer_t:
- case TST_image2d_t:
- case TST_image2d_array_t:
- case TST_image3d_t:
return false;
case TST_decltype:
case DeclSpec::TST_underlyingType: return "__underlying_type";
case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
case DeclSpec::TST_atomic: return "_Atomic";
- case DeclSpec::TST_image1d_t: return "image1d_t";
- case DeclSpec::TST_image1d_array_t: return "image1d_array_t";
- case DeclSpec::TST_image1d_buffer_t: return "image1d_buffer_t";
- case DeclSpec::TST_image2d_t: return "image2d_t";
- case DeclSpec::TST_image2d_array_t: return "image2d_array_t";
- case DeclSpec::TST_image3d_t: return "image3d_t";
case DeclSpec::TST_error: return "(error)";
}
llvm_unreachable("Unknown typespec!");
case TST_class:
case TST_auto:
case TST_unknown_anytype:
- case TST_image1d_t:
- case TST_image1d_array_t:
- case TST_image1d_buffer_t:
- case TST_image2d_t:
- case TST_image2d_array_t:
- case TST_image3d_t:
case TST_error:
break;
}
}
break;
- case DeclSpec::TST_image1d_t:
- Result = Context.OCLImage1dTy;
- break;
-
- case DeclSpec::TST_image1d_array_t:
- Result = Context.OCLImage1dArrayTy;
- break;
-
- case DeclSpec::TST_image1d_buffer_t:
- Result = Context.OCLImage1dBufferTy;
- break;
-
- case DeclSpec::TST_image2d_t:
- Result = Context.OCLImage2dTy;
- break;
-
- case DeclSpec::TST_image2d_array_t:
- Result = Context.OCLImage2dArrayTy;
- break;
-
- case DeclSpec::TST_image3d_t:
- Result = Context.OCLImage3dTy;
- break;
-
case DeclSpec::TST_error:
Result = Context.IntTy;
declarator.setInvalidType(true);
-//===--- ASTCommon.cpp - Common stuff for ASTReader/ASTWriter----*- C++ -*-===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This file defines common functions that both ASTReader and ASTWriter use.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "ASTCommon.h"\r
-#include "clang/Basic/IdentifierTable.h"\r
-#include "clang/Serialization/ASTDeserializationListener.h"\r
-#include "llvm/ADT/StringExtras.h"\r
-\r
-using namespace clang;\r
-\r
-// Give ASTDeserializationListener's VTable a home.\r
-ASTDeserializationListener::~ASTDeserializationListener() { }\r
-\r
-serialization::TypeIdx\r
-serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {\r
- unsigned ID = 0;\r
- switch (BT->getKind()) {\r
- case BuiltinType::Void: ID = PREDEF_TYPE_VOID_ID; break;\r
- case BuiltinType::Bool: ID = PREDEF_TYPE_BOOL_ID; break;\r
- case BuiltinType::Char_U: ID = PREDEF_TYPE_CHAR_U_ID; break;\r
- case BuiltinType::UChar: ID = PREDEF_TYPE_UCHAR_ID; break;\r
- case BuiltinType::UShort: ID = PREDEF_TYPE_USHORT_ID; break;\r
- case BuiltinType::UInt: ID = PREDEF_TYPE_UINT_ID; break;\r
- case BuiltinType::ULong: ID = PREDEF_TYPE_ULONG_ID; break;\r
- case BuiltinType::ULongLong: ID = PREDEF_TYPE_ULONGLONG_ID; break;\r
- case BuiltinType::UInt128: ID = PREDEF_TYPE_UINT128_ID; break;\r
- case BuiltinType::Char_S: ID = PREDEF_TYPE_CHAR_S_ID; break;\r
- case BuiltinType::SChar: ID = PREDEF_TYPE_SCHAR_ID; break;\r
- case BuiltinType::WChar_S:\r
- case BuiltinType::WChar_U: ID = PREDEF_TYPE_WCHAR_ID; break;\r
- case BuiltinType::Short: ID = PREDEF_TYPE_SHORT_ID; break;\r
- case BuiltinType::Int: ID = PREDEF_TYPE_INT_ID; break;\r
- case BuiltinType::Long: ID = PREDEF_TYPE_LONG_ID; break;\r
- case BuiltinType::LongLong: ID = PREDEF_TYPE_LONGLONG_ID; break;\r
- case BuiltinType::Int128: ID = PREDEF_TYPE_INT128_ID; break;\r
- case BuiltinType::Half: ID = PREDEF_TYPE_HALF_ID; break;\r
- case BuiltinType::Float: ID = PREDEF_TYPE_FLOAT_ID; break;\r
- case BuiltinType::Double: ID = PREDEF_TYPE_DOUBLE_ID; break;\r
- case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break;\r
- case BuiltinType::NullPtr: ID = PREDEF_TYPE_NULLPTR_ID; break;\r
- case BuiltinType::Char16: ID = PREDEF_TYPE_CHAR16_ID; break;\r
- case BuiltinType::Char32: ID = PREDEF_TYPE_CHAR32_ID; break;\r
- case BuiltinType::Overload: ID = PREDEF_TYPE_OVERLOAD_ID; break;\r
- case BuiltinType::BoundMember:ID = PREDEF_TYPE_BOUND_MEMBER; break;\r
- case BuiltinType::PseudoObject:ID = PREDEF_TYPE_PSEUDO_OBJECT;break;\r
- case BuiltinType::Dependent: ID = PREDEF_TYPE_DEPENDENT_ID; break;\r
- case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY; break;\r
- case BuiltinType::ARCUnbridgedCast:\r
- ID = PREDEF_TYPE_ARC_UNBRIDGED_CAST; break;\r
- case BuiltinType::ObjCId: ID = PREDEF_TYPE_OBJC_ID; break;\r
- case BuiltinType::ObjCClass: ID = PREDEF_TYPE_OBJC_CLASS; break;\r
- case BuiltinType::ObjCSel: ID = PREDEF_TYPE_OBJC_SEL; break;\r
- case BuiltinType::OCLImage1d: ID = PREDEF_TYPE_IMAGE1D_ID; break;\r
- case BuiltinType::OCLImage1dArray: ID = PREDEF_TYPE_IMAGE1D_ARR_ID; break;\r
- case BuiltinType::OCLImage1dBuffer: ID = PREDEF_TYPE_IMAGE1D_BUFF_ID; break;\r
- case BuiltinType::OCLImage2d: ID = PREDEF_TYPE_IMAGE2D_ID; break;\r
- case BuiltinType::OCLImage2dArray: ID = PREDEF_TYPE_IMAGE2D_ARR_ID; break;\r
- case BuiltinType::OCLImage3d: ID = PREDEF_TYPE_IMAGE3D_ID; break;\r
- case BuiltinType::BuiltinFn:\r
- ID = PREDEF_TYPE_BUILTIN_FN; break;\r
-\r
- }\r
-\r
- return TypeIdx(ID);\r
-}\r
-\r
-unsigned serialization::ComputeHash(Selector Sel) {\r
- unsigned N = Sel.getNumArgs();\r
- if (N == 0)\r
- ++N;\r
- unsigned R = 5381;\r
- for (unsigned I = 0; I != N; ++I)\r
- if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))\r
- R = llvm::HashString(II->getName(), R);\r
- return R;\r
-}\r
+//===--- ASTCommon.cpp - Common stuff for ASTReader/ASTWriter----*- 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 common functions that both ASTReader and ASTWriter use.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTCommon.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace clang;
+
+// Give ASTDeserializationListener's VTable a home.
+ASTDeserializationListener::~ASTDeserializationListener() { }
+
+serialization::TypeIdx
+serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
+ unsigned ID = 0;
+ switch (BT->getKind()) {
+ case BuiltinType::Void: ID = PREDEF_TYPE_VOID_ID; break;
+ case BuiltinType::Bool: ID = PREDEF_TYPE_BOOL_ID; break;
+ case BuiltinType::Char_U: ID = PREDEF_TYPE_CHAR_U_ID; break;
+ case BuiltinType::UChar: ID = PREDEF_TYPE_UCHAR_ID; break;
+ case BuiltinType::UShort: ID = PREDEF_TYPE_USHORT_ID; break;
+ case BuiltinType::UInt: ID = PREDEF_TYPE_UINT_ID; break;
+ case BuiltinType::ULong: ID = PREDEF_TYPE_ULONG_ID; break;
+ case BuiltinType::ULongLong: ID = PREDEF_TYPE_ULONGLONG_ID; break;
+ case BuiltinType::UInt128: ID = PREDEF_TYPE_UINT128_ID; break;
+ case BuiltinType::Char_S: ID = PREDEF_TYPE_CHAR_S_ID; break;
+ case BuiltinType::SChar: ID = PREDEF_TYPE_SCHAR_ID; break;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U: ID = PREDEF_TYPE_WCHAR_ID; break;
+ case BuiltinType::Short: ID = PREDEF_TYPE_SHORT_ID; break;
+ case BuiltinType::Int: ID = PREDEF_TYPE_INT_ID; break;
+ case BuiltinType::Long: ID = PREDEF_TYPE_LONG_ID; break;
+ case BuiltinType::LongLong: ID = PREDEF_TYPE_LONGLONG_ID; break;
+ case BuiltinType::Int128: ID = PREDEF_TYPE_INT128_ID; break;
+ case BuiltinType::Half: ID = PREDEF_TYPE_HALF_ID; break;
+ case BuiltinType::Float: ID = PREDEF_TYPE_FLOAT_ID; break;
+ case BuiltinType::Double: ID = PREDEF_TYPE_DOUBLE_ID; break;
+ case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break;
+ case BuiltinType::NullPtr: ID = PREDEF_TYPE_NULLPTR_ID; break;
+ case BuiltinType::Char16: ID = PREDEF_TYPE_CHAR16_ID; break;
+ case BuiltinType::Char32: ID = PREDEF_TYPE_CHAR32_ID; break;
+ case BuiltinType::Overload: ID = PREDEF_TYPE_OVERLOAD_ID; break;
+ case BuiltinType::BoundMember:ID = PREDEF_TYPE_BOUND_MEMBER; break;
+ case BuiltinType::PseudoObject:ID = PREDEF_TYPE_PSEUDO_OBJECT;break;
+ case BuiltinType::Dependent: ID = PREDEF_TYPE_DEPENDENT_ID; break;
+ case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY; break;
+ case BuiltinType::ARCUnbridgedCast:
+ ID = PREDEF_TYPE_ARC_UNBRIDGED_CAST; break;
+ case BuiltinType::ObjCId: ID = PREDEF_TYPE_OBJC_ID; break;
+ case BuiltinType::ObjCClass: ID = PREDEF_TYPE_OBJC_CLASS; break;
+ case BuiltinType::ObjCSel: ID = PREDEF_TYPE_OBJC_SEL; break;
+ case BuiltinType::BuiltinFn:
+ ID = PREDEF_TYPE_BUILTIN_FN; break;
+
+ }
+
+ return TypeIdx(ID);
+}
+
+unsigned serialization::ComputeHash(Selector Sel) {
+ unsigned N = Sel.getNumArgs();
+ if (N == 0)
+ ++N;
+ unsigned R = 5381;
+ for (unsigned I = 0; I != N; ++I)
+ if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
+ R = llvm::HashString(II->getName(), R);
+ return R;
+}
-//===--- ASTReader.cpp - AST File Reader ------------------------*- C++ -*-===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This file defines the ASTReader class, which reads AST files.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "clang/Serialization/ASTReader.h"\r
-#include "ASTCommon.h"\r
-#include "ASTReaderInternals.h"\r
-#include "clang/AST/ASTConsumer.h"\r
-#include "clang/AST/ASTContext.h"\r
-#include "clang/AST/DeclTemplate.h"\r
-#include "clang/AST/Expr.h"\r
-#include "clang/AST/ExprCXX.h"\r
-#include "clang/AST/NestedNameSpecifier.h"\r
-#include "clang/AST/Type.h"\r
-#include "clang/AST/TypeLocVisitor.h"\r
-#include "clang/Basic/FileManager.h"\r
-#include "clang/Basic/FileSystemStatCache.h"\r
-#include "clang/Basic/OnDiskHashTable.h"\r
-#include "clang/Basic/SourceManager.h"\r
-#include "clang/Basic/SourceManagerInternals.h"\r
-#include "clang/Basic/TargetInfo.h"\r
-#include "clang/Basic/TargetOptions.h"\r
-#include "clang/Basic/Version.h"\r
-#include "clang/Basic/VersionTuple.h"\r
-#include "clang/Lex/HeaderSearch.h"\r
-#include "clang/Lex/HeaderSearchOptions.h"\r
-#include "clang/Lex/MacroInfo.h"\r
-#include "clang/Lex/PreprocessingRecord.h"\r
-#include "clang/Lex/Preprocessor.h"\r
-#include "clang/Lex/PreprocessorOptions.h"\r
-#include "clang/Sema/Scope.h"\r
-#include "clang/Sema/Sema.h"\r
-#include "clang/Serialization/ASTDeserializationListener.h"\r
-#include "clang/Serialization/ModuleManager.h"\r
-#include "clang/Serialization/SerializationDiagnostic.h"\r
-#include "llvm/ADT/StringExtras.h"\r
-#include "llvm/Bitcode/BitstreamReader.h"\r
-#include "llvm/Support/ErrorHandling.h"\r
-#include "llvm/Support/FileSystem.h"\r
-#include "llvm/Support/MemoryBuffer.h"\r
-#include "llvm/Support/Path.h"\r
-#include "llvm/Support/SaveAndRestore.h"\r
-#include "llvm/Support/system_error.h"\r
-#include <algorithm>\r
-#include <cstdio>\r
-#include <iterator>\r
-\r
-using namespace clang;\r
-using namespace clang::serialization;\r
-using namespace clang::serialization::reader;\r
-\r
-//===----------------------------------------------------------------------===//\r
-// PCH validator implementation\r
-//===----------------------------------------------------------------------===//\r
-\r
-ASTReaderListener::~ASTReaderListener() {}\r
-\r
-/// \brief Compare the given set of language options against an existing set of\r
-/// language options.\r
-///\r
-/// \param Diags If non-NULL, diagnostics will be emitted via this engine.\r
-///\r
-/// \returns true if the languagae options mis-match, false otherwise.\r
-static bool checkLanguageOptions(const LangOptions &LangOpts,\r
- const LangOptions &ExistingLangOpts,\r
- DiagnosticsEngine *Diags) {\r
-#define LANGOPT(Name, Bits, Default, Description) \\r
- if (ExistingLangOpts.Name != LangOpts.Name) { \\r
- if (Diags) \\r
- Diags->Report(diag::err_pch_langopt_mismatch) \\r
- << Description << LangOpts.Name << ExistingLangOpts.Name; \\r
- return true; \\r
- }\r
-\r
-#define VALUE_LANGOPT(Name, Bits, Default, Description) \\r
- if (ExistingLangOpts.Name != LangOpts.Name) { \\r
- if (Diags) \\r
- Diags->Report(diag::err_pch_langopt_value_mismatch) \\r
- << Description; \\r
- return true; \\r
- }\r
-\r
-#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \\r
- if (ExistingLangOpts.get##Name() != LangOpts.get##Name()) { \\r
- if (Diags) \\r
- Diags->Report(diag::err_pch_langopt_value_mismatch) \\r
- << Description; \\r
- return true; \\r
- }\r
-\r
-#define BENIGN_LANGOPT(Name, Bits, Default, Description)\r
-#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)\r
-#include "clang/Basic/LangOptions.def"\r
-\r
- if (ExistingLangOpts.ObjCRuntime != LangOpts.ObjCRuntime) {\r
- if (Diags)\r
- Diags->Report(diag::err_pch_langopt_value_mismatch)\r
- << "target Objective-C runtime";\r
- return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-/// \brief Compare the given set of target options against an existing set of\r
-/// target options.\r
-///\r
-/// \param Diags If non-NULL, diagnostics will be emitted via this engine.\r
-///\r
-/// \returns true if the target options mis-match, false otherwise.\r
-static bool checkTargetOptions(const TargetOptions &TargetOpts,\r
- const TargetOptions &ExistingTargetOpts,\r
- DiagnosticsEngine *Diags) {\r
-#define CHECK_TARGET_OPT(Field, Name) \\r
- if (TargetOpts.Field != ExistingTargetOpts.Field) { \\r
- if (Diags) \\r
- Diags->Report(diag::err_pch_targetopt_mismatch) \\r
- << Name << TargetOpts.Field << ExistingTargetOpts.Field; \\r
- return true; \\r
- }\r
-\r
- CHECK_TARGET_OPT(Triple, "target");\r
- CHECK_TARGET_OPT(CPU, "target CPU");\r
- CHECK_TARGET_OPT(ABI, "target ABI");\r
- CHECK_TARGET_OPT(CXXABI, "target C++ ABI");\r
- CHECK_TARGET_OPT(LinkerVersion, "target linker version");\r
-#undef CHECK_TARGET_OPT\r
-\r
- // Compare feature sets.\r
- SmallVector<StringRef, 4> ExistingFeatures(\r
- ExistingTargetOpts.FeaturesAsWritten.begin(),\r
- ExistingTargetOpts.FeaturesAsWritten.end());\r
- SmallVector<StringRef, 4> ReadFeatures(TargetOpts.FeaturesAsWritten.begin(),\r
- TargetOpts.FeaturesAsWritten.end());\r
- std::sort(ExistingFeatures.begin(), ExistingFeatures.end());\r
- std::sort(ReadFeatures.begin(), ReadFeatures.end());\r
-\r
- unsigned ExistingIdx = 0, ExistingN = ExistingFeatures.size();\r
- unsigned ReadIdx = 0, ReadN = ReadFeatures.size();\r
- while (ExistingIdx < ExistingN && ReadIdx < ReadN) {\r
- if (ExistingFeatures[ExistingIdx] == ReadFeatures[ReadIdx]) {\r
- ++ExistingIdx;\r
- ++ReadIdx;\r
- continue;\r
- }\r
-\r
- if (ReadFeatures[ReadIdx] < ExistingFeatures[ExistingIdx]) {\r
- if (Diags)\r
- Diags->Report(diag::err_pch_targetopt_feature_mismatch)\r
- << false << ReadFeatures[ReadIdx];\r
- return true;\r
- }\r
-\r
- if (Diags)\r
- Diags->Report(diag::err_pch_targetopt_feature_mismatch)\r
- << true << ExistingFeatures[ExistingIdx];\r
- return true;\r
- }\r
-\r
- if (ExistingIdx < ExistingN) {\r
- if (Diags)\r
- Diags->Report(diag::err_pch_targetopt_feature_mismatch)\r
- << true << ExistingFeatures[ExistingIdx];\r
- return true;\r
- }\r
-\r
- if (ReadIdx < ReadN) {\r
- if (Diags)\r
- Diags->Report(diag::err_pch_targetopt_feature_mismatch)\r
- << false << ReadFeatures[ReadIdx];\r
- return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-bool\r
-PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts,\r
- bool Complain) {\r
- const LangOptions &ExistingLangOpts = PP.getLangOpts();\r
- return checkLanguageOptions(LangOpts, ExistingLangOpts,\r
- Complain? &Reader.Diags : 0);\r
-}\r
-\r
-bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,\r
- bool Complain) {\r
- const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts();\r
- return checkTargetOptions(TargetOpts, ExistingTargetOpts,\r
- Complain? &Reader.Diags : 0);\r
-}\r
-\r
-namespace {\r
- typedef llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >\r
- MacroDefinitionsMap;\r
-}\r
-\r
-/// \brief Collect the macro definitions provided by the given preprocessor\r
-/// options.\r
-static void collectMacroDefinitions(const PreprocessorOptions &PPOpts,\r
- MacroDefinitionsMap &Macros,\r
- SmallVectorImpl<StringRef> *MacroNames = 0){\r
- for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) {\r
- StringRef Macro = PPOpts.Macros[I].first;\r
- bool IsUndef = PPOpts.Macros[I].second;\r
-\r
- std::pair<StringRef, StringRef> MacroPair = Macro.split('=');\r
- StringRef MacroName = MacroPair.first;\r
- StringRef MacroBody = MacroPair.second;\r
-\r
- // For an #undef'd macro, we only care about the name.\r
- if (IsUndef) {\r
- if (MacroNames && !Macros.count(MacroName))\r
- MacroNames->push_back(MacroName);\r
-\r
- Macros[MacroName] = std::make_pair("", true);\r
- continue;\r
- }\r
-\r
- // For a #define'd macro, figure out the actual definition.\r
- if (MacroName.size() == Macro.size())\r
- MacroBody = "1";\r
- else {\r
- // Note: GCC drops anything following an end-of-line character.\r
- StringRef::size_type End = MacroBody.find_first_of("\n\r");\r
- MacroBody = MacroBody.substr(0, End);\r
- }\r
-\r
- if (MacroNames && !Macros.count(MacroName))\r
- MacroNames->push_back(MacroName);\r
- Macros[MacroName] = std::make_pair(MacroBody, false);\r
- }\r
-}\r
- \r
-/// \brief Check the preprocessor options deserialized from the control block\r
-/// against the preprocessor options in an existing preprocessor.\r
-///\r
-/// \param Diags If non-null, produce diagnostics for any mismatches incurred.\r
-static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,\r
- const PreprocessorOptions &ExistingPPOpts,\r
- DiagnosticsEngine *Diags,\r
- FileManager &FileMgr,\r
- std::string &SuggestedPredefines) {\r
- // Check macro definitions.\r
- MacroDefinitionsMap ASTFileMacros;\r
- collectMacroDefinitions(PPOpts, ASTFileMacros);\r
- MacroDefinitionsMap ExistingMacros;\r
- SmallVector<StringRef, 4> ExistingMacroNames;\r
- collectMacroDefinitions(ExistingPPOpts, ExistingMacros, &ExistingMacroNames);\r
-\r
- for (unsigned I = 0, N = ExistingMacroNames.size(); I != N; ++I) {\r
- // Dig out the macro definition in the existing preprocessor options.\r
- StringRef MacroName = ExistingMacroNames[I];\r
- std::pair<StringRef, bool> Existing = ExistingMacros[MacroName];\r
-\r
- // Check whether we know anything about this macro name or not.\r
- llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >::iterator Known\r
- = ASTFileMacros.find(MacroName);\r
- if (Known == ASTFileMacros.end()) {\r
- // FIXME: Check whether this identifier was referenced anywhere in the\r
- // AST file. If so, we should reject the AST file. Unfortunately, this\r
- // information isn't in the control block. What shall we do about it?\r
-\r
- if (Existing.second) {\r
- SuggestedPredefines += "#undef ";\r
- SuggestedPredefines += MacroName.str();\r
- SuggestedPredefines += '\n';\r
- } else {\r
- SuggestedPredefines += "#define ";\r
- SuggestedPredefines += MacroName.str();\r
- SuggestedPredefines += ' ';\r
- SuggestedPredefines += Existing.first.str();\r
- SuggestedPredefines += '\n';\r
- }\r
- continue;\r
- }\r
-\r
- // If the macro was defined in one but undef'd in the other, we have a\r
- // conflict.\r
- if (Existing.second != Known->second.second) {\r
- if (Diags) {\r
- Diags->Report(diag::err_pch_macro_def_undef)\r
- << MacroName << Known->second.second;\r
- }\r
- return true;\r
- }\r
-\r
- // If the macro was #undef'd in both, or if the macro bodies are identical,\r
- // it's fine.\r
- if (Existing.second || Existing.first == Known->second.first)\r
- continue;\r
-\r
- // The macro bodies differ; complain.\r
- if (Diags) {\r
- Diags->Report(diag::err_pch_macro_def_conflict)\r
- << MacroName << Known->second.first << Existing.first;\r
- }\r
- return true;\r
- }\r
-\r
- // Check whether we're using predefines.\r
- if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines) {\r
- if (Diags) {\r
- Diags->Report(diag::err_pch_undef) << ExistingPPOpts.UsePredefines;\r
- }\r
- return true;\r
- }\r
-\r
- // Compute the #include and #include_macros lines we need.\r
- for (unsigned I = 0, N = ExistingPPOpts.Includes.size(); I != N; ++I) {\r
- StringRef File = ExistingPPOpts.Includes[I];\r
- if (File == ExistingPPOpts.ImplicitPCHInclude)\r
- continue;\r
-\r
- if (std::find(PPOpts.Includes.begin(), PPOpts.Includes.end(), File)\r
- != PPOpts.Includes.end())\r
- continue;\r
-\r
- SuggestedPredefines += "#include \"";\r
- SuggestedPredefines +=\r
- HeaderSearch::NormalizeDashIncludePath(File, FileMgr);\r
- SuggestedPredefines += "\"\n";\r
- }\r
-\r
- for (unsigned I = 0, N = ExistingPPOpts.MacroIncludes.size(); I != N; ++I) {\r
- StringRef File = ExistingPPOpts.MacroIncludes[I];\r
- if (std::find(PPOpts.MacroIncludes.begin(), PPOpts.MacroIncludes.end(),\r
- File)\r
- != PPOpts.MacroIncludes.end())\r
- continue;\r
-\r
- SuggestedPredefines += "#__include_macros \"";\r
- SuggestedPredefines +=\r
- HeaderSearch::NormalizeDashIncludePath(File, FileMgr);\r
- SuggestedPredefines += "\"\n##\n";\r
- }\r
-\r
- return false;\r
-}\r
-\r
-bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,\r
- bool Complain,\r
- std::string &SuggestedPredefines) {\r
- const PreprocessorOptions &ExistingPPOpts = PP.getPreprocessorOpts();\r
-\r
- return checkPreprocessorOptions(PPOpts, ExistingPPOpts,\r
- Complain? &Reader.Diags : 0,\r
- PP.getFileManager(),\r
- SuggestedPredefines);\r
-}\r
-\r
-void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI,\r
- unsigned ID) {\r
- PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID);\r
- ++NumHeaderInfos;\r
-}\r
-\r
-void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) {\r
- PP.setCounterValue(Value);\r
-}\r
-\r
-//===----------------------------------------------------------------------===//\r
-// AST reader implementation\r
-//===----------------------------------------------------------------------===//\r
-\r
-void\r
-ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) {\r
- DeserializationListener = Listener;\r
-}\r
-\r
-\r
-\r
-unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) {\r
- return serialization::ComputeHash(Sel);\r
-}\r
-\r
-\r
-std::pair<unsigned, unsigned>\r
-ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) {\r
- using namespace clang::io;\r
- unsigned KeyLen = ReadUnalignedLE16(d);\r
- unsigned DataLen = ReadUnalignedLE16(d);\r
- return std::make_pair(KeyLen, DataLen);\r
-}\r
-\r
-ASTSelectorLookupTrait::internal_key_type \r
-ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {\r
- using namespace clang::io;\r
- SelectorTable &SelTable = Reader.getContext().Selectors;\r
- unsigned N = ReadUnalignedLE16(d);\r
- IdentifierInfo *FirstII\r
- = Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));\r
- if (N == 0)\r
- return SelTable.getNullarySelector(FirstII);\r
- else if (N == 1)\r
- return SelTable.getUnarySelector(FirstII);\r
-\r
- SmallVector<IdentifierInfo *, 16> Args;\r
- Args.push_back(FirstII);\r
- for (unsigned I = 1; I != N; ++I)\r
- Args.push_back(Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)));\r
-\r
- return SelTable.getSelector(N, Args.data());\r
-}\r
-\r
-ASTSelectorLookupTrait::data_type \r
-ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, \r
- unsigned DataLen) {\r
- using namespace clang::io;\r
-\r
- data_type Result;\r
-\r
- Result.ID = Reader.getGlobalSelectorID(F, ReadUnalignedLE32(d));\r
- unsigned NumInstanceMethods = ReadUnalignedLE16(d);\r
- unsigned NumFactoryMethods = ReadUnalignedLE16(d);\r
-\r
- // Load instance methods\r
- for (unsigned I = 0; I != NumInstanceMethods; ++I) {\r
- if (ObjCMethodDecl *Method\r
- = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))\r
- Result.Instance.push_back(Method);\r
- }\r
-\r
- // Load factory methods\r
- for (unsigned I = 0; I != NumFactoryMethods; ++I) {\r
- if (ObjCMethodDecl *Method\r
- = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))\r
- Result.Factory.push_back(Method);\r
- }\r
-\r
- return Result;\r
-}\r
-\r
-unsigned ASTIdentifierLookupTrait::ComputeHash(const internal_key_type& a) {\r
- return llvm::HashString(StringRef(a.first, a.second));\r
-}\r
-\r
-std::pair<unsigned, unsigned>\r
-ASTIdentifierLookupTrait::ReadKeyDataLength(const unsigned char*& d) {\r
- using namespace clang::io;\r
- unsigned DataLen = ReadUnalignedLE16(d);\r
- unsigned KeyLen = ReadUnalignedLE16(d);\r
- return std::make_pair(KeyLen, DataLen);\r
-}\r
-\r
-std::pair<const char*, unsigned>\r
-ASTIdentifierLookupTrait::ReadKey(const unsigned char* d, unsigned n) {\r
- assert(n >= 2 && d[n-1] == '\0');\r
- return std::make_pair((const char*) d, n-1);\r
-}\r
-\r
-IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,\r
- const unsigned char* d,\r
- unsigned DataLen) {\r
- using namespace clang::io;\r
- unsigned RawID = ReadUnalignedLE32(d);\r
- bool IsInteresting = RawID & 0x01;\r
-\r
- // Wipe out the "is interesting" bit.\r
- RawID = RawID >> 1;\r
-\r
- IdentID ID = Reader.getGlobalIdentifierID(F, RawID);\r
- if (!IsInteresting) {\r
- // For uninteresting identifiers, just build the IdentifierInfo\r
- // and associate it with the persistent ID.\r
- IdentifierInfo *II = KnownII;\r
- if (!II) {\r
- II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));\r
- KnownII = II;\r
- }\r
- Reader.SetIdentifierInfo(ID, II);\r
- II->setIsFromAST();\r
- Reader.markIdentifierUpToDate(II); \r
- return II;\r
- }\r
-\r
- unsigned ObjCOrBuiltinID = ReadUnalignedLE16(d);\r
- unsigned Bits = ReadUnalignedLE16(d);\r
- bool CPlusPlusOperatorKeyword = Bits & 0x01;\r
- Bits >>= 1;\r
- bool HasRevertedTokenIDToIdentifier = Bits & 0x01;\r
- Bits >>= 1;\r
- bool Poisoned = Bits & 0x01;\r
- Bits >>= 1;\r
- bool ExtensionToken = Bits & 0x01;\r
- Bits >>= 1;\r
- bool hadMacroDefinition = Bits & 0x01;\r
- Bits >>= 1;\r
-\r
- assert(Bits == 0 && "Extra bits in the identifier?");\r
- DataLen -= 8;\r
-\r
- // Build the IdentifierInfo itself and link the identifier ID with\r
- // the new IdentifierInfo.\r
- IdentifierInfo *II = KnownII;\r
- if (!II) {\r
- II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));\r
- KnownII = II;\r
- }\r
- Reader.markIdentifierUpToDate(II);\r
- II->setIsFromAST();\r
-\r
- // Set or check the various bits in the IdentifierInfo structure.\r
- // Token IDs are read-only.\r
- if (HasRevertedTokenIDToIdentifier)\r
- II->RevertTokenIDToIdentifier();\r
- II->setObjCOrBuiltinID(ObjCOrBuiltinID);\r
- assert(II->isExtensionToken() == ExtensionToken &&\r
- "Incorrect extension token flag");\r
- (void)ExtensionToken;\r
- if (Poisoned)\r
- II->setIsPoisoned(true);\r
- assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&\r
- "Incorrect C++ operator keyword flag");\r
- (void)CPlusPlusOperatorKeyword;\r
-\r
- // If this identifier is a macro, deserialize the macro\r
- // definition.\r
- if (hadMacroDefinition) {\r
- SmallVector<MacroID, 4> MacroIDs;\r
- while (uint32_t LocalID = ReadUnalignedLE32(d)) {\r
- MacroIDs.push_back(Reader.getGlobalMacroID(F, LocalID));\r
- DataLen -= 4;\r
- }\r
- DataLen -= 4;\r
- Reader.setIdentifierIsMacro(II, MacroIDs);\r
- }\r
-\r
- Reader.SetIdentifierInfo(ID, II);\r
-\r
- // Read all of the declarations visible at global scope with this\r
- // name.\r
- if (DataLen > 0) {\r
- SmallVector<uint32_t, 4> DeclIDs;\r
- for (; DataLen > 0; DataLen -= 4)\r
- DeclIDs.push_back(Reader.getGlobalDeclID(F, ReadUnalignedLE32(d)));\r
- Reader.SetGloballyVisibleDecls(II, DeclIDs);\r
- }\r
-\r
- return II;\r
-}\r
-\r
-unsigned \r
-ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) const {\r
- llvm::FoldingSetNodeID ID;\r
- ID.AddInteger(Key.Kind);\r
-\r
- switch (Key.Kind) {\r
- case DeclarationName::Identifier:\r
- case DeclarationName::CXXLiteralOperatorName:\r
- ID.AddString(((IdentifierInfo*)Key.Data)->getName());\r
- break;\r
- case DeclarationName::ObjCZeroArgSelector:\r
- case DeclarationName::ObjCOneArgSelector:\r
- case DeclarationName::ObjCMultiArgSelector:\r
- ID.AddInteger(serialization::ComputeHash(Selector(Key.Data)));\r
- break;\r
- case DeclarationName::CXXOperatorName:\r
- ID.AddInteger((OverloadedOperatorKind)Key.Data);\r
- break;\r
- case DeclarationName::CXXConstructorName:\r
- case DeclarationName::CXXDestructorName:\r
- case DeclarationName::CXXConversionFunctionName:\r
- case DeclarationName::CXXUsingDirective:\r
- break;\r
- }\r
-\r
- return ID.ComputeHash();\r
-}\r
-\r
-ASTDeclContextNameLookupTrait::internal_key_type \r
-ASTDeclContextNameLookupTrait::GetInternalKey(\r
- const external_key_type& Name) const {\r
- DeclNameKey Key;\r
- Key.Kind = Name.getNameKind();\r
- switch (Name.getNameKind()) {\r
- case DeclarationName::Identifier:\r
- Key.Data = (uint64_t)Name.getAsIdentifierInfo();\r
- break;\r
- case DeclarationName::ObjCZeroArgSelector:\r
- case DeclarationName::ObjCOneArgSelector:\r
- case DeclarationName::ObjCMultiArgSelector:\r
- Key.Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr();\r
- break;\r
- case DeclarationName::CXXOperatorName:\r
- Key.Data = Name.getCXXOverloadedOperator();\r
- break;\r
- case DeclarationName::CXXLiteralOperatorName:\r
- Key.Data = (uint64_t)Name.getCXXLiteralIdentifier();\r
- break;\r
- case DeclarationName::CXXConstructorName:\r
- case DeclarationName::CXXDestructorName:\r
- case DeclarationName::CXXConversionFunctionName:\r
- case DeclarationName::CXXUsingDirective:\r
- Key.Data = 0;\r
- break;\r
- }\r
-\r
- return Key;\r
-}\r
-\r
-std::pair<unsigned, unsigned>\r
-ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char*& d) {\r
- using namespace clang::io;\r
- unsigned KeyLen = ReadUnalignedLE16(d);\r
- unsigned DataLen = ReadUnalignedLE16(d);\r
- return std::make_pair(KeyLen, DataLen);\r
-}\r
-\r
-ASTDeclContextNameLookupTrait::internal_key_type \r
-ASTDeclContextNameLookupTrait::ReadKey(const unsigned char* d, unsigned) {\r
- using namespace clang::io;\r
-\r
- DeclNameKey Key;\r
- Key.Kind = (DeclarationName::NameKind)*d++;\r
- switch (Key.Kind) {\r
- case DeclarationName::Identifier:\r
- Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));\r
- break;\r
- case DeclarationName::ObjCZeroArgSelector:\r
- case DeclarationName::ObjCOneArgSelector:\r
- case DeclarationName::ObjCMultiArgSelector:\r
- Key.Data =\r
- (uint64_t)Reader.getLocalSelector(F, ReadUnalignedLE32(d))\r
- .getAsOpaquePtr();\r
- break;\r
- case DeclarationName::CXXOperatorName:\r
- Key.Data = *d++; // OverloadedOperatorKind\r
- break;\r
- case DeclarationName::CXXLiteralOperatorName:\r
- Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));\r
- break;\r
- case DeclarationName::CXXConstructorName:\r
- case DeclarationName::CXXDestructorName:\r
- case DeclarationName::CXXConversionFunctionName:\r
- case DeclarationName::CXXUsingDirective:\r
- Key.Data = 0;\r
- break;\r
- }\r
-\r
- return Key;\r
-}\r
-\r
-ASTDeclContextNameLookupTrait::data_type \r
-ASTDeclContextNameLookupTrait::ReadData(internal_key_type, \r
- const unsigned char* d,\r
- unsigned DataLen) {\r
- using namespace clang::io;\r
- unsigned NumDecls = ReadUnalignedLE16(d);\r
- LE32DeclID *Start = (LE32DeclID *)d;\r
- return std::make_pair(Start, Start + NumDecls);\r
-}\r
-\r
-bool ASTReader::ReadDeclContextStorage(ModuleFile &M,\r
- llvm::BitstreamCursor &Cursor,\r
- const std::pair<uint64_t, uint64_t> &Offsets,\r
- DeclContextInfo &Info) {\r
- SavedStreamPosition SavedPosition(Cursor);\r
- // First the lexical decls.\r
- if (Offsets.first != 0) {\r
- Cursor.JumpToBit(Offsets.first);\r
-\r
- RecordData Record;\r
- const char *Blob;\r
- unsigned BlobLen;\r
- unsigned Code = Cursor.ReadCode();\r
- unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);\r
- if (RecCode != DECL_CONTEXT_LEXICAL) {\r
- Error("Expected lexical block");\r
- return true;\r
- }\r
-\r
- Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair*>(Blob);\r
- Info.NumLexicalDecls = BlobLen / sizeof(KindDeclIDPair);\r
- }\r
-\r
- // Now the lookup table.\r
- if (Offsets.second != 0) {\r
- Cursor.JumpToBit(Offsets.second);\r
-\r
- RecordData Record;\r
- const char *Blob;\r
- unsigned BlobLen;\r
- unsigned Code = Cursor.ReadCode();\r
- unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);\r
- if (RecCode != DECL_CONTEXT_VISIBLE) {\r
- Error("Expected visible lookup table block");\r
- return true;\r
- }\r
- Info.NameLookupTableData\r
- = ASTDeclContextNameLookupTable::Create(\r
- (const unsigned char *)Blob + Record[0],\r
- (const unsigned char *)Blob,\r
- ASTDeclContextNameLookupTrait(*this, M));\r
- }\r
-\r
- return false;\r
-}\r
-\r
-void ASTReader::Error(StringRef Msg) {\r
- Error(diag::err_fe_pch_malformed, Msg);\r
-}\r
-\r
-void ASTReader::Error(unsigned DiagID,\r
- StringRef Arg1, StringRef Arg2) {\r
- if (Diags.isDiagnosticInFlight())\r
- Diags.SetDelayedDiagnostic(DiagID, Arg1, Arg2);\r
- else\r
- Diag(DiagID) << Arg1 << Arg2;\r
-}\r
-\r
-//===----------------------------------------------------------------------===//\r
-// Source Manager Deserialization\r
-//===----------------------------------------------------------------------===//\r
-\r
-/// \brief Read the line table in the source manager block.\r
-/// \returns true if there was an error.\r
-bool ASTReader::ParseLineTable(ModuleFile &F,\r
- SmallVectorImpl<uint64_t> &Record) {\r
- unsigned Idx = 0;\r
- LineTableInfo &LineTable = SourceMgr.getLineTable();\r
-\r
- // Parse the file names\r
- std::map<int, int> FileIDs;\r
- for (int I = 0, N = Record[Idx++]; I != N; ++I) {\r
- // Extract the file name\r
- unsigned FilenameLen = Record[Idx++];\r
- std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);\r
- Idx += FilenameLen;\r
- MaybeAddSystemRootToFilename(F, Filename);\r
- FileIDs[I] = LineTable.getLineTableFilenameID(Filename);\r
- }\r
-\r
- // Parse the line entries\r
- std::vector<LineEntry> Entries;\r
- while (Idx < Record.size()) {\r
- int FID = Record[Idx++];\r
- assert(FID >= 0 && "Serialized line entries for non-local file.");\r
- // Remap FileID from 1-based old view.\r
- FID += F.SLocEntryBaseID - 1;\r
-\r
- // Extract the line entries\r
- unsigned NumEntries = Record[Idx++];\r
- assert(NumEntries && "Numentries is 00000");\r
- Entries.clear();\r
- Entries.reserve(NumEntries);\r
- for (unsigned I = 0; I != NumEntries; ++I) {\r
- unsigned FileOffset = Record[Idx++];\r
- unsigned LineNo = Record[Idx++];\r
- int FilenameID = FileIDs[Record[Idx++]];\r
- SrcMgr::CharacteristicKind FileKind\r
- = (SrcMgr::CharacteristicKind)Record[Idx++];\r
- unsigned IncludeOffset = Record[Idx++];\r
- Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,\r
- FileKind, IncludeOffset));\r
- }\r
- LineTable.AddEntry(FileID::get(FID), Entries);\r
- }\r
-\r
- return false;\r
-}\r
-\r
-/// \brief Read a source manager block\r
-bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {\r
- using namespace SrcMgr;\r
-\r
- llvm::BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor;\r
-\r
- // Set the source-location entry cursor to the current position in\r
- // the stream. This cursor will be used to read the contents of the\r
- // source manager block initially, and then lazily read\r
- // source-location entries as needed.\r
- SLocEntryCursor = F.Stream;\r
-\r
- // The stream itself is going to skip over the source manager block.\r
- if (F.Stream.SkipBlock()) {\r
- Error("malformed block record in AST file");\r
- return true;\r
- }\r
-\r
- // Enter the source manager block.\r
- if (SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID)) {\r
- Error("malformed source manager block record in AST file");\r
- return true;\r
- }\r
-\r
- RecordData Record;\r
- while (true) {\r
- unsigned Code = SLocEntryCursor.ReadCode();\r
- if (Code == llvm::bitc::END_BLOCK) {\r
- if (SLocEntryCursor.ReadBlockEnd()) {\r
- Error("error at end of Source Manager block in AST file");\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- if (Code == llvm::bitc::ENTER_SUBBLOCK) {\r
- // No known subblocks, always skip them.\r
- SLocEntryCursor.ReadSubBlockID();\r
- if (SLocEntryCursor.SkipBlock()) {\r
- Error("malformed block record in AST file");\r
- return true;\r
- }\r
- continue;\r
- }\r
-\r
- if (Code == llvm::bitc::DEFINE_ABBREV) {\r
- SLocEntryCursor.ReadAbbrevRecord();\r
- continue;\r
- }\r
-\r
- // Read a record.\r
- const char *BlobStart;\r
- unsigned BlobLen;\r
- Record.clear();\r
- switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {\r
- default: // Default behavior: ignore.\r
- break;\r
-\r
- case SM_SLOC_FILE_ENTRY:\r
- case SM_SLOC_BUFFER_ENTRY:\r
- case SM_SLOC_EXPANSION_ENTRY:\r
- // Once we hit one of the source location entries, we're done.\r
- return false;\r
- }\r
- }\r
-}\r
-\r
-/// \brief If a header file is not found at the path that we expect it to be\r
-/// and the PCH file was moved from its original location, try to resolve the\r
-/// file by assuming that header+PCH were moved together and the header is in\r
-/// the same place relative to the PCH.\r
-static std::string\r
-resolveFileRelativeToOriginalDir(const std::string &Filename,\r
- const std::string &OriginalDir,\r
- const std::string &CurrDir) {\r
- assert(OriginalDir != CurrDir &&\r
- "No point trying to resolve the file if the PCH dir didn't change");\r
- using namespace llvm::sys;\r
- SmallString<128> filePath(Filename);\r
- fs::make_absolute(filePath);\r
- assert(path::is_absolute(OriginalDir));\r
- SmallString<128> currPCHPath(CurrDir);\r
-\r
- path::const_iterator fileDirI = path::begin(path::parent_path(filePath)),\r
- fileDirE = path::end(path::parent_path(filePath));\r
- path::const_iterator origDirI = path::begin(OriginalDir),\r
- origDirE = path::end(OriginalDir);\r
- // Skip the common path components from filePath and OriginalDir.\r
- while (fileDirI != fileDirE && origDirI != origDirE &&\r
- *fileDirI == *origDirI) {\r
- ++fileDirI;\r
- ++origDirI;\r
- }\r
- for (; origDirI != origDirE; ++origDirI)\r
- path::append(currPCHPath, "..");\r
- path::append(currPCHPath, fileDirI, fileDirE);\r
- path::append(currPCHPath, path::filename(Filename));\r
- return currPCHPath.str();\r
-}\r
-\r
-bool ASTReader::ReadSLocEntry(int ID) {\r
- if (ID == 0)\r
- return false;\r
-\r
- if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) {\r
- Error("source location entry ID out-of-range for AST file");\r
- return true;\r
- }\r
-\r
- ModuleFile *F = GlobalSLocEntryMap.find(-ID)->second;\r
- F->SLocEntryCursor.JumpToBit(F->SLocEntryOffsets[ID - F->SLocEntryBaseID]);\r
- llvm::BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor;\r
- unsigned BaseOffset = F->SLocEntryBaseOffset;\r
-\r
- ++NumSLocEntriesRead;\r
- unsigned Code = SLocEntryCursor.ReadCode();\r
- if (Code == llvm::bitc::END_BLOCK ||\r
- Code == llvm::bitc::ENTER_SUBBLOCK ||\r
- Code == llvm::bitc::DEFINE_ABBREV) {\r
- Error("incorrectly-formatted source location entry in AST file");\r
- return true;\r
- }\r
-\r
- RecordData Record;\r
- const char *BlobStart;\r
- unsigned BlobLen;\r
- switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {\r
- default:\r
- Error("incorrectly-formatted source location entry in AST file");\r
- return true;\r
-\r
- case SM_SLOC_FILE_ENTRY: {\r
- // We will detect whether a file changed and return 'Failure' for it, but\r
- // we will also try to fail gracefully by setting up the SLocEntry.\r
- unsigned InputID = Record[4];\r
- InputFile IF = getInputFile(*F, InputID);\r
- const FileEntry *File = IF.getPointer();\r
- bool OverriddenBuffer = IF.getInt();\r
-\r
- if (!IF.getPointer())\r
- return true;\r
-\r
- SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);\r
- if (IncludeLoc.isInvalid() && F->Kind != MK_MainFile) {\r
- // This is the module's main file.\r
- IncludeLoc = getImportLocation(F);\r
- }\r
- SrcMgr::CharacteristicKind\r
- FileCharacter = (SrcMgr::CharacteristicKind)Record[2];\r
- FileID FID = SourceMgr.createFileID(File, IncludeLoc, FileCharacter,\r
- ID, BaseOffset + Record[0]);\r
- SrcMgr::FileInfo &FileInfo =\r
- const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile());\r
- FileInfo.NumCreatedFIDs = Record[5];\r
- if (Record[3])\r
- FileInfo.setHasLineDirectives();\r
-\r
- const DeclID *FirstDecl = F->FileSortedDecls + Record[6];\r
- unsigned NumFileDecls = Record[7];\r
- if (NumFileDecls) {\r
- assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?");\r
- FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl,\r
- NumFileDecls));\r
- }\r
- \r
- const SrcMgr::ContentCache *ContentCache\r
- = SourceMgr.getOrCreateContentCache(File,\r
- /*isSystemFile=*/FileCharacter != SrcMgr::C_User);\r
- if (OverriddenBuffer && !ContentCache->BufferOverridden &&\r
- ContentCache->ContentsEntry == ContentCache->OrigEntry) {\r
- unsigned Code = SLocEntryCursor.ReadCode();\r
- Record.clear();\r
- unsigned RecCode\r
- = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);\r
- \r
- if (RecCode != SM_SLOC_BUFFER_BLOB) {\r
- Error("AST record has invalid code");\r
- return true;\r
- }\r
- \r
- llvm::MemoryBuffer *Buffer\r
- = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),\r
- File->getName());\r
- SourceMgr.overrideFileContents(File, Buffer);\r
- }\r
-\r
- break;\r
- }\r
-\r
- case SM_SLOC_BUFFER_ENTRY: {\r
- const char *Name = BlobStart;\r
- unsigned Offset = Record[0];\r
- SrcMgr::CharacteristicKind\r
- FileCharacter = (SrcMgr::CharacteristicKind)Record[2];\r
- SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);\r
- if (IncludeLoc.isInvalid() && F->Kind == MK_Module) {\r
- IncludeLoc = getImportLocation(F);\r
- }\r
- unsigned Code = SLocEntryCursor.ReadCode();\r
- Record.clear();\r
- unsigned RecCode\r
- = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);\r
-\r
- if (RecCode != SM_SLOC_BUFFER_BLOB) {\r
- Error("AST record has invalid code");\r
- return true;\r
- }\r
-\r
- llvm::MemoryBuffer *Buffer\r
- = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),\r
- Name);\r
- SourceMgr.createFileIDForMemBuffer(Buffer, FileCharacter, ID,\r
- BaseOffset + Offset, IncludeLoc);\r
- break;\r
- }\r
-\r
- case SM_SLOC_EXPANSION_ENTRY: {\r
- SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1]);\r
- SourceMgr.createExpansionLoc(SpellingLoc,\r
- ReadSourceLocation(*F, Record[2]),\r
- ReadSourceLocation(*F, Record[3]),\r
- Record[4],\r
- ID,\r
- BaseOffset + Record[0]);\r
- break;\r
- }\r
- }\r
-\r
- return false;\r
-}\r
-\r
-std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) {\r
- if (ID == 0)\r
- return std::make_pair(SourceLocation(), "");\r
-\r
- if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) {\r
- Error("source location entry ID out-of-range for AST file");\r
- return std::make_pair(SourceLocation(), "");\r
- }\r
-\r
- // Find which module file this entry lands in.\r
- ModuleFile *M = GlobalSLocEntryMap.find(-ID)->second;\r
- if (M->Kind != MK_Module)\r
- return std::make_pair(SourceLocation(), "");\r
-\r
- // FIXME: Can we map this down to a particular submodule? That would be\r
- // ideal.\r
- return std::make_pair(M->ImportLoc, llvm::sys::path::stem(M->FileName));\r
-}\r
-\r
-/// \brief Find the location where the module F is imported.\r
-SourceLocation ASTReader::getImportLocation(ModuleFile *F) {\r
- if (F->ImportLoc.isValid())\r
- return F->ImportLoc;\r
- \r
- // Otherwise we have a PCH. It's considered to be "imported" at the first\r
- // location of its includer.\r
- if (F->ImportedBy.empty() || !F->ImportedBy[0]) {\r
- // Main file is the importer. We assume that it is the first entry in the\r
- // entry table. We can't ask the manager, because at the time of PCH loading\r
- // the main file entry doesn't exist yet.\r
- // The very first entry is the invalid instantiation loc, which takes up\r
- // offsets 0 and 1.\r
- return SourceLocation::getFromRawEncoding(2U);\r
- }\r
- //return F->Loaders[0]->FirstLoc;\r
- return F->ImportedBy[0]->FirstLoc;\r
-}\r
-\r
-/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the\r
-/// specified cursor. Read the abbreviations that are at the top of the block\r
-/// and then leave the cursor pointing into the block.\r
-bool ASTReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,\r
- unsigned BlockID) {\r
- if (Cursor.EnterSubBlock(BlockID)) {\r
- Error("malformed block record in AST file");\r
- return Failure;\r
- }\r
-\r
- while (true) {\r
- uint64_t Offset = Cursor.GetCurrentBitNo();\r
- unsigned Code = Cursor.ReadCode();\r
-\r
- // We expect all abbrevs to be at the start of the block.\r
- if (Code != llvm::bitc::DEFINE_ABBREV) {\r
- Cursor.JumpToBit(Offset);\r
- return false;\r
- }\r
- Cursor.ReadAbbrevRecord();\r
- }\r
-}\r
-\r
-void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,\r
- MacroInfo *Hint) {\r
- llvm::BitstreamCursor &Stream = F.MacroCursor;\r
-\r
- // Keep track of where we are in the stream, then jump back there\r
- // after reading this macro.\r
- SavedStreamPosition SavedPosition(Stream);\r
-\r
- Stream.JumpToBit(Offset);\r
- RecordData Record;\r
- SmallVector<IdentifierInfo*, 16> MacroArgs;\r
- MacroInfo *Macro = 0;\r
-\r
- // RAII object to add the loaded macro information once we're done\r
- // adding tokens.\r
- struct AddLoadedMacroInfoRAII {\r
- Preprocessor &PP;\r
- MacroInfo *Hint;\r
- MacroInfo *MI;\r
- IdentifierInfo *II;\r
-\r
- AddLoadedMacroInfoRAII(Preprocessor &PP, MacroInfo *Hint)\r
- : PP(PP), Hint(Hint), MI(), II() { }\r
- ~AddLoadedMacroInfoRAII( ) {\r
- if (MI) {\r
- // Finally, install the macro.\r
- PP.addLoadedMacroInfo(II, MI, Hint);\r
- }\r
- }\r
- } AddLoadedMacroInfo(PP, Hint);\r
-\r
- while (true) {\r
- unsigned Code = Stream.ReadCode();\r
- switch (Code) {\r
- case llvm::bitc::END_BLOCK:\r
- return;\r
-\r
- case llvm::bitc::ENTER_SUBBLOCK:\r
- // No known subblocks, always skip them.\r
- Stream.ReadSubBlockID();\r
- if (Stream.SkipBlock()) {\r
- Error("malformed block record in AST file");\r
- return;\r
- }\r
- continue;\r
-\r
- case llvm::bitc::DEFINE_ABBREV:\r
- Stream.ReadAbbrevRecord();\r
- continue;\r
- default: break;\r
- }\r
-\r
- // Read a record.\r
- const char *BlobStart = 0;\r
- unsigned BlobLen = 0;\r
- Record.clear();\r
- PreprocessorRecordTypes RecType =\r
- (PreprocessorRecordTypes)Stream.ReadRecord(Code, Record, BlobStart,\r
- BlobLen);\r
- switch (RecType) {\r
- case PP_MACRO_OBJECT_LIKE:\r
- case PP_MACRO_FUNCTION_LIKE: {\r
- // If we already have a macro, that means that we've hit the end\r
- // of the definition of the macro we were looking for. We're\r
- // done.\r
- if (Macro)\r
- return;\r
-\r
- IdentifierInfo *II = getLocalIdentifier(F, Record[0]);\r
- if (II == 0) {\r
- Error("macro must have a name in AST file");\r
- return;\r
- }\r
-\r
- unsigned GlobalID = getGlobalMacroID(F, Record[1]);\r
-\r
- // If this macro has already been loaded, don't do so again.\r
- if (MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS])\r
- return;\r
-\r
- SubmoduleID GlobalSubmoduleID = getGlobalSubmoduleID(F, Record[2]);\r
- unsigned NextIndex = 3;\r
- SourceLocation Loc = ReadSourceLocation(F, Record, NextIndex);\r
- MacroInfo *MI = PP.AllocateMacroInfo(Loc);\r
-\r
- // Record this macro.\r
- MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS] = MI;\r
-\r
- SourceLocation UndefLoc = ReadSourceLocation(F, Record, NextIndex);\r
- if (UndefLoc.isValid())\r
- MI->setUndefLoc(UndefLoc);\r
-\r
- MI->setIsUsed(Record[NextIndex++]);\r
- MI->setIsFromAST();\r
-\r
- bool IsPublic = Record[NextIndex++];\r
- MI->setVisibility(IsPublic, ReadSourceLocation(F, Record, NextIndex));\r
-\r
- if (RecType == PP_MACRO_FUNCTION_LIKE) {\r
- // Decode function-like macro info.\r
- bool isC99VarArgs = Record[NextIndex++];\r
- bool isGNUVarArgs = Record[NextIndex++];\r
- bool hasCommaPasting = Record[NextIndex++];\r
- MacroArgs.clear();\r
- unsigned NumArgs = Record[NextIndex++];\r
- for (unsigned i = 0; i != NumArgs; ++i)\r
- MacroArgs.push_back(getLocalIdentifier(F, Record[NextIndex++]));\r
-\r
- // Install function-like macro info.\r
- MI->setIsFunctionLike();\r
- if (isC99VarArgs) MI->setIsC99Varargs();\r
- if (isGNUVarArgs) MI->setIsGNUVarargs();\r
- if (hasCommaPasting) MI->setHasCommaPasting();\r
- MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),\r
- PP.getPreprocessorAllocator());\r
- }\r
-\r
- if (DeserializationListener)\r
- DeserializationListener->MacroRead(GlobalID, MI);\r
-\r
- // If an update record marked this as undefined, do so now.\r
- // FIXME: Only if the submodule this update came from is visible?\r
- MacroUpdatesMap::iterator Update = MacroUpdates.find(GlobalID);\r
- if (Update != MacroUpdates.end()) {\r
- if (MI->getUndefLoc().isInvalid()) {\r
- for (unsigned I = 0, N = Update->second.size(); I != N; ++I) {\r
- bool Hidden = false;\r
- if (unsigned SubmoduleID = Update->second[I].first) {\r
- if (Module *Owner = getSubmodule(SubmoduleID)) {\r
- if (Owner->NameVisibility == Module::Hidden) {\r
- // Note that this #undef is hidden.\r
- Hidden = true;\r
-\r
- // Record this hiding for later.\r
- HiddenNamesMap[Owner].push_back(\r
- HiddenName(II, MI, Update->second[I].second.UndefLoc));\r
- }\r
- }\r
- }\r
-\r
- if (!Hidden) {\r
- MI->setUndefLoc(Update->second[I].second.UndefLoc);\r
- if (PPMutationListener *Listener = PP.getPPMutationListener())\r
- Listener->UndefinedMacro(MI);\r
- break;\r
- }\r
- }\r
- }\r
- MacroUpdates.erase(Update);\r
- }\r
-\r
- // Determine whether this macro definition is visible.\r
- bool Hidden = !MI->isPublic();\r
- if (!Hidden && GlobalSubmoduleID) {\r
- if (Module *Owner = getSubmodule(GlobalSubmoduleID)) {\r
- if (Owner->NameVisibility == Module::Hidden) {\r
- // The owning module is not visible, and this macro definition\r
- // should not be, either.\r
- Hidden = true;\r
-\r
- // Note that this macro definition was hidden because its owning\r
- // module is not yet visible.\r
- HiddenNamesMap[Owner].push_back(HiddenName(II, MI));\r
- }\r
- }\r
- }\r
- MI->setHidden(Hidden);\r
-\r
- // Make sure we install the macro once we're done.\r
- AddLoadedMacroInfo.MI = MI;\r
- AddLoadedMacroInfo.II = II;\r
-\r
- // Remember that we saw this macro last so that we add the tokens that\r
- // form its body to it.\r
- Macro = MI;\r
-\r
- if (NextIndex + 1 == Record.size() && PP.getPreprocessingRecord() &&\r
- Record[NextIndex]) {\r
- // We have a macro definition. Register the association\r
- PreprocessedEntityID\r
- GlobalID = getGlobalPreprocessedEntityID(F, Record[NextIndex]);\r
- PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();\r
- PPRec.RegisterMacroDefinition(Macro,\r
- PPRec.getPPEntityID(GlobalID-1, /*isLoaded=*/true));\r
- }\r
-\r
- ++NumMacrosRead;\r
- break;\r
- }\r
-\r
- case PP_TOKEN: {\r
- // If we see a TOKEN before a PP_MACRO_*, then the file is\r
- // erroneous, just pretend we didn't see this.\r
- if (Macro == 0) break;\r
-\r
- Token Tok;\r
- Tok.startToken();\r
- Tok.setLocation(ReadSourceLocation(F, Record[0]));\r
- Tok.setLength(Record[1]);\r
- if (IdentifierInfo *II = getLocalIdentifier(F, Record[2]))\r
- Tok.setIdentifierInfo(II);\r
- Tok.setKind((tok::TokenKind)Record[3]);\r
- Tok.setFlag((Token::TokenFlags)Record[4]);\r
- Macro->AddTokenToBody(Tok);\r
- break;\r
- }\r
- }\r
- }\r
-}\r
-\r
-PreprocessedEntityID \r
-ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const {\r
- ContinuousRangeMap<uint32_t, int, 2>::const_iterator \r
- I = M.PreprocessedEntityRemap.find(LocalID - NUM_PREDEF_PP_ENTITY_IDS);\r
- assert(I != M.PreprocessedEntityRemap.end() \r
- && "Invalid index into preprocessed entity index remap");\r
- \r
- return LocalID + I->second;\r
-}\r
-\r
-unsigned HeaderFileInfoTrait::ComputeHash(const char *path) {\r
- return llvm::HashString(llvm::sys::path::filename(path));\r
-}\r
- \r
-HeaderFileInfoTrait::internal_key_type \r
-HeaderFileInfoTrait::GetInternalKey(const char *path) { return path; }\r
- \r
-bool HeaderFileInfoTrait::EqualKey(internal_key_type a, internal_key_type b) {\r
- if (strcmp(a, b) == 0)\r
- return true;\r
- \r
- if (llvm::sys::path::filename(a) != llvm::sys::path::filename(b))\r
- return false;\r
-\r
- // Determine whether the actual files are equivalent.\r
- bool Result = false;\r
- if (llvm::sys::fs::equivalent(a, b, Result))\r
- return false;\r
- \r
- return Result;\r
-}\r
- \r
-std::pair<unsigned, unsigned>\r
-HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) {\r
- unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);\r
- unsigned DataLen = (unsigned) *d++;\r
- return std::make_pair(KeyLen + 1, DataLen);\r
-}\r
- \r
-HeaderFileInfoTrait::data_type \r
-HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d,\r
- unsigned DataLen) {\r
- const unsigned char *End = d + DataLen;\r
- using namespace clang::io;\r
- HeaderFileInfo HFI;\r
- unsigned Flags = *d++;\r
- HFI.isImport = (Flags >> 5) & 0x01;\r
- HFI.isPragmaOnce = (Flags >> 4) & 0x01;\r
- HFI.DirInfo = (Flags >> 2) & 0x03;\r
- HFI.Resolved = (Flags >> 1) & 0x01;\r
- HFI.IndexHeaderMapHeader = Flags & 0x01;\r
- HFI.NumIncludes = ReadUnalignedLE16(d);\r
- HFI.ControllingMacroID = Reader.getGlobalIdentifierID(M, \r
- ReadUnalignedLE32(d));\r
- if (unsigned FrameworkOffset = ReadUnalignedLE32(d)) {\r
- // The framework offset is 1 greater than the actual offset, \r
- // since 0 is used as an indicator for "no framework name".\r
- StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);\r
- HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);\r
- }\r
- \r
- assert(End == d && "Wrong data length in HeaderFileInfo deserialization");\r
- (void)End;\r
- \r
- // This HeaderFileInfo was externally loaded.\r
- HFI.External = true;\r
- return HFI;\r
-}\r
-\r
-void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ArrayRef<MacroID> IDs){\r
- II->setHadMacroDefinition(true);\r
- assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");\r
- PendingMacroIDs[II].append(IDs.begin(), IDs.end());\r
-}\r
-\r
-void ASTReader::ReadDefinedMacros() {\r
- // Note that we are loading defined macros.\r
- Deserializing Macros(this);\r
-\r
- for (ModuleReverseIterator I = ModuleMgr.rbegin(),\r
- E = ModuleMgr.rend(); I != E; ++I) {\r
- llvm::BitstreamCursor &MacroCursor = (*I)->MacroCursor;\r
-\r
- // If there was no preprocessor block, skip this file.\r
- if (!MacroCursor.getBitStreamReader())\r
- continue;\r
-\r
- llvm::BitstreamCursor Cursor = MacroCursor;\r
- Cursor.JumpToBit((*I)->MacroStartOffset);\r
-\r
- RecordData Record;\r
- while (true) {\r
- unsigned Code = Cursor.ReadCode();\r
- if (Code == llvm::bitc::END_BLOCK)\r
- break;\r
-\r
- if (Code == llvm::bitc::ENTER_SUBBLOCK) {\r
- // No known subblocks, always skip them.\r
- Cursor.ReadSubBlockID();\r
- if (Cursor.SkipBlock()) {\r
- Error("malformed block record in AST file");\r
- return;\r
- }\r
- continue;\r
- }\r
-\r
- if (Code == llvm::bitc::DEFINE_ABBREV) {\r
- Cursor.ReadAbbrevRecord();\r
- continue;\r
- }\r
-\r
- // Read a record.\r
- const char *BlobStart;\r
- unsigned BlobLen;\r
- Record.clear();\r
- switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {\r
- default: // Default behavior: ignore.\r
- break;\r
-\r
- case PP_MACRO_OBJECT_LIKE:\r
- case PP_MACRO_FUNCTION_LIKE:\r
- getLocalIdentifier(**I, Record[0]);\r
- break;\r
-\r
- case PP_TOKEN:\r
- // Ignore tokens.\r
- break;\r
- }\r
- }\r
- }\r
-}\r
-\r
-namespace {\r
- /// \brief Visitor class used to look up identifirs in an AST file.\r
- class IdentifierLookupVisitor {\r
- StringRef Name;\r
- unsigned PriorGeneration;\r
- IdentifierInfo *Found;\r
- public:\r
- IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration) \r
- : Name(Name), PriorGeneration(PriorGeneration), Found() { }\r
- \r
- static bool visit(ModuleFile &M, void *UserData) {\r
- IdentifierLookupVisitor *This\r
- = static_cast<IdentifierLookupVisitor *>(UserData);\r
- \r
- // If we've already searched this module file, skip it now.\r
- if (M.Generation <= This->PriorGeneration)\r
- return true;\r
- \r
- ASTIdentifierLookupTable *IdTable\r
- = (ASTIdentifierLookupTable *)M.IdentifierLookupTable;\r
- if (!IdTable)\r
- return false;\r
- \r
- ASTIdentifierLookupTrait Trait(IdTable->getInfoObj().getReader(),\r
- M, This->Found);\r
- \r
- std::pair<const char*, unsigned> Key(This->Name.begin(), \r
- This->Name.size());\r
- ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Trait);\r
- if (Pos == IdTable->end())\r
- return false;\r
- \r
- // Dereferencing the iterator has the effect of building the\r
- // IdentifierInfo node and populating it with the various\r
- // declarations it needs.\r
- This->Found = *Pos;\r
- return true;\r
- }\r
- \r
- // \brief Retrieve the identifier info found within the module\r
- // files.\r
- IdentifierInfo *getIdentifierInfo() const { return Found; }\r
- };\r
-}\r
-\r
-void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {\r
- // Note that we are loading an identifier.\r
- Deserializing AnIdentifier(this);\r
-\r
- unsigned PriorGeneration = 0;\r
- if (getContext().getLangOpts().Modules)\r
- PriorGeneration = IdentifierGeneration[&II];\r
- \r
- IdentifierLookupVisitor Visitor(II.getName(), PriorGeneration);\r
- ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);\r
- markIdentifierUpToDate(&II);\r
-}\r
-\r
-void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) {\r
- if (!II)\r
- return;\r
- \r
- II->setOutOfDate(false);\r
-\r
- // Update the generation for this identifier.\r
- if (getContext().getLangOpts().Modules)\r
- IdentifierGeneration[II] = CurrentGeneration;\r
-}\r
-\r
-llvm::PointerIntPair<const FileEntry *, 1, bool> \r
-ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {\r
- // If this ID is bogus, just return an empty input file.\r
- if (ID == 0 || ID > F.InputFilesLoaded.size())\r
- return InputFile();\r
-\r
- // If we've already loaded this input file, return it.\r
- if (F.InputFilesLoaded[ID-1].getPointer())\r
- return F.InputFilesLoaded[ID-1];\r
-\r
- // Go find this input file.\r
- llvm::BitstreamCursor &Cursor = F.InputFilesCursor;\r
- SavedStreamPosition SavedPosition(Cursor);\r
- Cursor.JumpToBit(F.InputFileOffsets[ID-1]);\r
- \r
- unsigned Code = Cursor.ReadCode();\r
- RecordData Record;\r
- const char *BlobStart = 0;\r
- unsigned BlobLen = 0;\r
- switch ((InputFileRecordTypes)Cursor.ReadRecord(Code, Record,\r
- &BlobStart, &BlobLen)) {\r
- case INPUT_FILE: {\r
- unsigned StoredID = Record[0];\r
- assert(ID == StoredID && "Bogus stored ID or offset");\r
- (void)StoredID;\r
- off_t StoredSize = (off_t)Record[1];\r
- time_t StoredTime = (time_t)Record[2];\r
- bool Overridden = (bool)Record[3];\r
- \r
- // Get the file entry for this input file.\r
- StringRef OrigFilename(BlobStart, BlobLen);\r
- std::string Filename = OrigFilename;\r
- MaybeAddSystemRootToFilename(F, Filename);\r
- const FileEntry *File \r
- = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime)\r
- : FileMgr.getFile(Filename, /*OpenFile=*/false);\r
- \r
- // If we didn't find the file, resolve it relative to the\r
- // original directory from which this AST file was created.\r
- if (File == 0 && !F.OriginalDir.empty() && !CurrentDir.empty() &&\r
- F.OriginalDir != CurrentDir) {\r
- std::string Resolved = resolveFileRelativeToOriginalDir(Filename,\r
- F.OriginalDir,\r
- CurrentDir);\r
- if (!Resolved.empty())\r
- File = FileMgr.getFile(Resolved);\r
- }\r
- \r
- // For an overridden file, create a virtual file with the stored\r
- // size/timestamp.\r
- if (Overridden && File == 0) {\r
- File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime);\r
- }\r
- \r
- if (File == 0) {\r
- if (Complain) {\r
- std::string ErrorStr = "could not find file '";\r
- ErrorStr += Filename;\r
- ErrorStr += "' referenced by AST file";\r
- Error(ErrorStr.c_str());\r
- }\r
- return InputFile();\r
- }\r
- \r
- // Note that we've loaded this input file.\r
- F.InputFilesLoaded[ID-1] = InputFile(File, Overridden);\r
- \r
- // Check if there was a request to override the contents of the file\r
- // that was part of the precompiled header. Overridding such a file\r
- // can lead to problems when lexing using the source locations from the\r
- // PCH.\r
- SourceManager &SM = getSourceManager();\r
- if (!Overridden && SM.isFileOverridden(File)) {\r
- Error(diag::err_fe_pch_file_overridden, Filename);\r
- // After emitting the diagnostic, recover by disabling the override so\r
- // that the original file will be used.\r
- SM.disableFileContentsOverride(File);\r
- // The FileEntry is a virtual file entry with the size of the contents\r
- // that would override the original contents. Set it to the original's\r
- // size/time.\r
- FileMgr.modifyFileEntry(const_cast<FileEntry*>(File),\r
- StoredSize, StoredTime);\r
- }\r
-\r
- // For an overridden file, there is nothing to validate.\r
- if (Overridden)\r
- return InputFile(File, Overridden);\r
-\r
- if ((StoredSize != File->getSize()\r
-#if !defined(LLVM_ON_WIN32)\r
- // In our regression testing, the Windows file system seems to\r
- // have inconsistent modification times that sometimes\r
- // erroneously trigger this error-handling path.\r
- || StoredTime != File->getModificationTime()\r
-#endif\r
- )) {\r
- if (Complain)\r
- Error(diag::err_fe_pch_file_modified, Filename);\r
- \r
- return InputFile();\r
- }\r
-\r
- return InputFile(File, Overridden);\r
- }\r
- }\r
-\r
- return InputFile();\r
-}\r
-\r
-const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) {\r
- ModuleFile &M = ModuleMgr.getPrimaryModule();\r
- std::string Filename = filenameStrRef;\r
- MaybeAddSystemRootToFilename(M, Filename);\r
- const FileEntry *File = FileMgr.getFile(Filename);\r
- if (File == 0 && !M.OriginalDir.empty() && !CurrentDir.empty() &&\r
- M.OriginalDir != CurrentDir) {\r
- std::string resolved = resolveFileRelativeToOriginalDir(Filename,\r
- M.OriginalDir,\r
- CurrentDir);\r
- if (!resolved.empty())\r
- File = FileMgr.getFile(resolved);\r
- }\r
-\r
- return File;\r
-}\r
-\r
-/// \brief If we are loading a relocatable PCH file, and the filename is\r
-/// not an absolute path, add the system root to the beginning of the file\r
-/// name.\r
-void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M,\r
- std::string &Filename) {\r
- // If this is not a relocatable PCH file, there's nothing to do.\r
- if (!M.RelocatablePCH)\r
- return;\r
-\r
- if (Filename.empty() || llvm::sys::path::is_absolute(Filename))\r
- return;\r
-\r
- if (isysroot.empty()) {\r
- // If no system root was given, default to '/'\r
- Filename.insert(Filename.begin(), '/');\r
- return;\r
- }\r
-\r
- unsigned Length = isysroot.size();\r
- if (isysroot[Length - 1] != '/')\r
- Filename.insert(Filename.begin(), '/');\r
-\r
- Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end());\r
-}\r
-\r
-ASTReader::ASTReadResult\r
-ASTReader::ReadControlBlock(ModuleFile &F,\r
- llvm::SmallVectorImpl<ImportedModule> &Loaded,\r
- unsigned ClientLoadCapabilities) {\r
- llvm::BitstreamCursor &Stream = F.Stream;\r
-\r
- if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {\r
- Error("malformed block record in AST file");\r
- return Failure;\r
- }\r
-\r
- // Read all of the records and blocks in the control block.\r
- RecordData Record;\r
- while (!Stream.AtEndOfStream()) {\r
- unsigned Code = Stream.ReadCode();\r
- if (Code == llvm::bitc::END_BLOCK) {\r
- if (Stream.ReadBlockEnd()) {\r
- Error("error at end of control block in AST file");\r
- return Failure;\r
- }\r
-\r
- // Validate all of the input files.\r
- if (!DisableValidation) {\r
- bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;\r
- for (unsigned I = 0, N = Record[0]; I < N; ++I)\r
- if (!getInputFile(F, I+1, Complain).getPointer())\r
- return OutOfDate;\r
- }\r
-\r
- return Success;\r
- }\r
-\r
- if (Code == llvm::bitc::ENTER_SUBBLOCK) {\r
- switch (Stream.ReadSubBlockID()) {\r
- case INPUT_FILES_BLOCK_ID:\r
- F.InputFilesCursor = Stream;\r
- if (Stream.SkipBlock() || // Skip with the main cursor\r
- // Read the abbreviations\r
- ReadBlockAbbrevs(F.InputFilesCursor, INPUT_FILES_BLOCK_ID)) {\r
- Error("malformed block record in AST file");\r
- return Failure;\r
- }\r
- continue;\r
- \r
- default:\r
- if (!Stream.SkipBlock())\r
- continue;\r
- break;\r
- }\r
-\r
- Error("malformed block record in AST file");\r
- return Failure;\r
- }\r
-\r
- if (Code == llvm::bitc::DEFINE_ABBREV) {\r
- Stream.ReadAbbrevRecord();\r
- continue;\r
- }\r
-\r
- // Read and process a record.\r
- Record.clear();\r
- const char *BlobStart = 0;\r
- unsigned BlobLen = 0;\r
- switch ((ControlRecordTypes)Stream.ReadRecord(Code, Record,\r
- &BlobStart, &BlobLen)) {\r
- case METADATA: {\r
- if (Record[0] != VERSION_MAJOR && !DisableValidation) {\r
- if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)\r
- Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old\r
- : diag::warn_pch_version_too_new);\r
- return VersionMismatch;\r
- }\r
-\r
- bool hasErrors = Record[5];\r
- if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {\r
- Diag(diag::err_pch_with_compiler_errors);\r
- return HadErrors;\r
- }\r
-\r
- F.RelocatablePCH = Record[4];\r
-\r
- const std::string &CurBranch = getClangFullRepositoryVersion();\r
- StringRef ASTBranch(BlobStart, BlobLen);\r
- if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {\r
- if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)\r
- Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch;\r
- return VersionMismatch;\r
- }\r
- break;\r
- }\r
-\r
- case IMPORTS: {\r
- // Load each of the imported PCH files. \r
- unsigned Idx = 0, N = Record.size();\r
- while (Idx < N) {\r
- // Read information about the AST file.\r
- ModuleKind ImportedKind = (ModuleKind)Record[Idx++];\r
- // The import location will be the local one for now; we will adjust\r
- // all import locations of module imports after the global source\r
- // location info are setup.\r
- SourceLocation ImportLoc =\r
- SourceLocation::getFromRawEncoding(Record[Idx++]);\r
- unsigned Length = Record[Idx++];\r
- SmallString<128> ImportedFile(Record.begin() + Idx,\r
- Record.begin() + Idx + Length);\r
- Idx += Length;\r
-\r
- // Load the AST file.\r
- switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded,\r
- ClientLoadCapabilities)) {\r
- case Failure: return Failure;\r
- // If we have to ignore the dependency, we'll have to ignore this too.\r
- case OutOfDate: return OutOfDate;\r
- case VersionMismatch: return VersionMismatch;\r
- case ConfigurationMismatch: return ConfigurationMismatch;\r
- case HadErrors: return HadErrors;\r
- case Success: break;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case LANGUAGE_OPTIONS: {\r
- bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;\r
- if (Listener && &F == *ModuleMgr.begin() &&\r
- ParseLanguageOptions(Record, Complain, *Listener) &&\r
- !DisableValidation)\r
- return ConfigurationMismatch;\r
- break;\r
- }\r
-\r
- case TARGET_OPTIONS: {\r
- bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;\r
- if (Listener && &F == *ModuleMgr.begin() &&\r
- ParseTargetOptions(Record, Complain, *Listener) &&\r
- !DisableValidation)\r
- return ConfigurationMismatch;\r
- break;\r
- }\r
-\r
- case DIAGNOSTIC_OPTIONS: {\r
- bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;\r
- if (Listener && &F == *ModuleMgr.begin() &&\r
- ParseDiagnosticOptions(Record, Complain, *Listener) &&\r
- !DisableValidation)\r
- return ConfigurationMismatch;\r
- break;\r
- }\r
-\r
- case FILE_SYSTEM_OPTIONS: {\r
- bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;\r
- if (Listener && &F == *ModuleMgr.begin() &&\r
- ParseFileSystemOptions(Record, Complain, *Listener) &&\r
- !DisableValidation)\r
- return ConfigurationMismatch;\r
- break;\r
- }\r
-\r
- case HEADER_SEARCH_OPTIONS: {\r
- bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;\r
- if (Listener && &F == *ModuleMgr.begin() &&\r
- ParseHeaderSearchOptions(Record, Complain, *Listener) &&\r
- !DisableValidation)\r
- return ConfigurationMismatch;\r
- break;\r
- }\r
-\r
- case PREPROCESSOR_OPTIONS: {\r
- bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;\r
- if (Listener && &F == *ModuleMgr.begin() &&\r
- ParsePreprocessorOptions(Record, Complain, *Listener,\r
- SuggestedPredefines) &&\r
- !DisableValidation)\r
- return ConfigurationMismatch;\r
- break;\r
- }\r
-\r
- case ORIGINAL_FILE:\r
- F.OriginalSourceFileID = FileID::get(Record[0]);\r
- F.ActualOriginalSourceFileName.assign(BlobStart, BlobLen);\r
- F.OriginalSourceFileName = F.ActualOriginalSourceFileName;\r
- MaybeAddSystemRootToFilename(F, F.OriginalSourceFileName);\r
- break;\r
-\r
- case ORIGINAL_FILE_ID:\r
- F.OriginalSourceFileID = FileID::get(Record[0]);\r
- break;\r
-\r
- case ORIGINAL_PCH_DIR:\r
- F.OriginalDir.assign(BlobStart, BlobLen);\r
- break;\r
-\r
- case INPUT_FILE_OFFSETS:\r
- F.InputFileOffsets = (const uint32_t *)BlobStart;\r
- F.InputFilesLoaded.resize(Record[0]);\r
- break;\r
- }\r
- }\r
-\r
- Error("premature end of bitstream in AST file");\r
- return Failure;\r
-}\r
-\r
-bool ASTReader::ReadASTBlock(ModuleFile &F) {\r
- llvm::BitstreamCursor &Stream = F.Stream;\r
-\r
- if (Stream.EnterSubBlock(AST_BLOCK_ID)) {\r
- Error("malformed block record in AST file");\r
- return true;\r
- }\r
-\r
- // Read all of the records and blocks for the AST file.\r
- RecordData Record;\r
- while (!Stream.AtEndOfStream()) {\r
- unsigned Code = Stream.ReadCode();\r
- if (Code == llvm::bitc::END_BLOCK) {\r
- if (Stream.ReadBlockEnd()) {\r
- Error("error at end of module block in AST file");\r
- return true;\r
- }\r
-\r
- DeclContext *DC = Context.getTranslationUnitDecl();\r
- if (!DC->hasExternalVisibleStorage() && DC->hasExternalLexicalStorage())\r
- DC->setMustBuildLookupTable();\r
-\r
- return false;\r
- }\r
-\r
- if (Code == llvm::bitc::ENTER_SUBBLOCK) {\r
- switch (Stream.ReadSubBlockID()) {\r
- case DECLTYPES_BLOCK_ID:\r
- // We lazily load the decls block, but we want to set up the\r
- // DeclsCursor cursor to point into it. Clone our current bitcode\r
- // cursor to it, enter the block and read the abbrevs in that block.\r
- // With the main cursor, we just skip over it.\r
- F.DeclsCursor = Stream;\r
- if (Stream.SkipBlock() || // Skip with the main cursor.\r
- // Read the abbrevs.\r
- ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) {\r
- Error("malformed block record in AST file");\r
- return true;\r
- }\r
- break;\r
-\r
- case DECL_UPDATES_BLOCK_ID:\r
- if (Stream.SkipBlock()) {\r
- Error("malformed block record in AST file");\r
- return true;\r
- }\r
- break;\r
-\r
- case PREPROCESSOR_BLOCK_ID:\r
- F.MacroCursor = Stream;\r
- if (!PP.getExternalSource())\r
- PP.setExternalSource(this);\r
-\r
- if (Stream.SkipBlock() ||\r
- ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) {\r
- Error("malformed block record in AST file");\r
- return true;\r
- }\r
- F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo();\r
- break;\r
-\r
- case PREPROCESSOR_DETAIL_BLOCK_ID:\r
- F.PreprocessorDetailCursor = Stream;\r
- if (Stream.SkipBlock() ||\r
- ReadBlockAbbrevs(F.PreprocessorDetailCursor, \r
- PREPROCESSOR_DETAIL_BLOCK_ID)) {\r
- Error("malformed preprocessor detail record in AST file");\r
- return true;\r
- }\r
- F.PreprocessorDetailStartOffset\r
- = F.PreprocessorDetailCursor.GetCurrentBitNo();\r
- \r
- if (!PP.getPreprocessingRecord())\r
- PP.createPreprocessingRecord();\r
- if (!PP.getPreprocessingRecord()->getExternalSource())\r
- PP.getPreprocessingRecord()->SetExternalSource(*this);\r
- break;\r
- \r
- case SOURCE_MANAGER_BLOCK_ID:\r
- if (ReadSourceManagerBlock(F))\r
- return true;\r
- break;\r
-\r
- case SUBMODULE_BLOCK_ID:\r
- if (ReadSubmoduleBlock(F))\r
- return true;\r
- break;\r
-\r
- case COMMENTS_BLOCK_ID: {\r
- llvm::BitstreamCursor C = Stream;\r
- if (Stream.SkipBlock() ||\r
- ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) {\r
- Error("malformed comments block in AST file");\r
- return true;\r
- }\r
- CommentsCursors.push_back(std::make_pair(C, &F));\r
- break;\r
- }\r
-\r
- default:\r
- if (!Stream.SkipBlock())\r
- break;\r
- Error("malformed block record in AST file");\r
- return true;\r
- }\r
- continue;\r
- }\r
-\r
- if (Code == llvm::bitc::DEFINE_ABBREV) {\r
- Stream.ReadAbbrevRecord();\r
- continue;\r
- }\r
-\r
- // Read and process a record.\r
- Record.clear();\r
- const char *BlobStart = 0;\r
- unsigned BlobLen = 0;\r
- switch ((ASTRecordTypes)Stream.ReadRecord(Code, Record,\r
- &BlobStart, &BlobLen)) {\r
- default: // Default behavior: ignore.\r
- break;\r
-\r
- case TYPE_OFFSET: {\r
- if (F.LocalNumTypes != 0) {\r
- Error("duplicate TYPE_OFFSET record in AST file");\r
- return true;\r
- }\r
- F.TypeOffsets = (const uint32_t *)BlobStart;\r
- F.LocalNumTypes = Record[0];\r
- unsigned LocalBaseTypeIndex = Record[1];\r
- F.BaseTypeIndex = getTotalNumTypes();\r
- \r
- if (F.LocalNumTypes > 0) {\r
- // Introduce the global -> local mapping for types within this module.\r
- GlobalTypeMap.insert(std::make_pair(getTotalNumTypes(), &F));\r
- \r
- // Introduce the local -> global mapping for types within this module.\r
- F.TypeRemap.insertOrReplace(\r
- std::make_pair(LocalBaseTypeIndex, \r
- F.BaseTypeIndex - LocalBaseTypeIndex));\r
- \r
- TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes);\r
- }\r
- break;\r
- }\r
- \r
- case DECL_OFFSET: {\r
- if (F.LocalNumDecls != 0) {\r
- Error("duplicate DECL_OFFSET record in AST file");\r
- return true;\r
- }\r
- F.DeclOffsets = (const DeclOffset *)BlobStart;\r
- F.LocalNumDecls = Record[0];\r
- unsigned LocalBaseDeclID = Record[1];\r
- F.BaseDeclID = getTotalNumDecls();\r
- \r
- if (F.LocalNumDecls > 0) {\r
- // Introduce the global -> local mapping for declarations within this \r
- // module.\r
- GlobalDeclMap.insert(\r
- std::make_pair(getTotalNumDecls() + NUM_PREDEF_DECL_IDS, &F));\r
- \r
- // Introduce the local -> global mapping for declarations within this\r
- // module.\r
- F.DeclRemap.insertOrReplace(\r
- std::make_pair(LocalBaseDeclID, F.BaseDeclID - LocalBaseDeclID));\r
- \r
- // Introduce the global -> local mapping for declarations within this\r
- // module.\r
- F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID;\r
- \r
- DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);\r
- }\r
- break;\r
- }\r
- \r
- case TU_UPDATE_LEXICAL: {\r
- DeclContext *TU = Context.getTranslationUnitDecl();\r
- DeclContextInfo &Info = F.DeclContextInfos[TU];\r
- Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair *>(BlobStart);\r
- Info.NumLexicalDecls \r
- = static_cast<unsigned int>(BlobLen / sizeof(KindDeclIDPair));\r
- TU->setHasExternalLexicalStorage(true);\r
- break;\r
- }\r
-\r
- case UPDATE_VISIBLE: {\r
- unsigned Idx = 0;\r
- serialization::DeclID ID = ReadDeclID(F, Record, Idx);\r
- ASTDeclContextNameLookupTable *Table =\r
- ASTDeclContextNameLookupTable::Create(\r
- (const unsigned char *)BlobStart + Record[Idx++],\r
- (const unsigned char *)BlobStart,\r
- ASTDeclContextNameLookupTrait(*this, F));\r
- if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID) { // Is it the TU?\r
- DeclContext *TU = Context.getTranslationUnitDecl();\r
- F.DeclContextInfos[TU].NameLookupTableData = Table;\r
- TU->setHasExternalVisibleStorage(true);\r
- } else\r
- PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F));\r
- break;\r
- }\r
-\r
- case IDENTIFIER_TABLE:\r
- F.IdentifierTableData = BlobStart;\r
- if (Record[0]) {\r
- F.IdentifierLookupTable\r
- = ASTIdentifierLookupTable::Create(\r
- (const unsigned char *)F.IdentifierTableData + Record[0],\r
- (const unsigned char *)F.IdentifierTableData,\r
- ASTIdentifierLookupTrait(*this, F));\r
- \r
- PP.getIdentifierTable().setExternalIdentifierLookup(this);\r
- }\r
- break;\r
-\r
- case IDENTIFIER_OFFSET: {\r
- if (F.LocalNumIdentifiers != 0) {\r
- Error("duplicate IDENTIFIER_OFFSET record in AST file");\r
- return true;\r
- }\r
- F.IdentifierOffsets = (const uint32_t *)BlobStart;\r
- F.LocalNumIdentifiers = Record[0];\r
- unsigned LocalBaseIdentifierID = Record[1];\r
- F.BaseIdentifierID = getTotalNumIdentifiers();\r
- \r
- if (F.LocalNumIdentifiers > 0) {\r
- // Introduce the global -> local mapping for identifiers within this\r
- // module.\r
- GlobalIdentifierMap.insert(std::make_pair(getTotalNumIdentifiers() + 1, \r
- &F));\r
- \r
- // Introduce the local -> global mapping for identifiers within this\r
- // module.\r
- F.IdentifierRemap.insertOrReplace(\r
- std::make_pair(LocalBaseIdentifierID,\r
- F.BaseIdentifierID - LocalBaseIdentifierID));\r
- \r
- IdentifiersLoaded.resize(IdentifiersLoaded.size() \r
- + F.LocalNumIdentifiers);\r
- }\r
- break;\r
- }\r
-\r
- case EXTERNAL_DEFINITIONS:\r
- for (unsigned I = 0, N = Record.size(); I != N; ++I)\r
- ExternalDefinitions.push_back(getGlobalDeclID(F, Record[I]));\r
- break;\r
-\r
- case SPECIAL_TYPES:\r
- for (unsigned I = 0, N = Record.size(); I != N; ++I)\r
- SpecialTypes.push_back(getGlobalTypeID(F, Record[I]));\r
- break;\r
-\r
- case STATISTICS:\r
- TotalNumStatements += Record[0];\r
- TotalNumMacros += Record[1];\r
- TotalLexicalDeclContexts += Record[2];\r
- TotalVisibleDeclContexts += Record[3];\r
- break;\r
-\r
- case UNUSED_FILESCOPED_DECLS:\r
- for (unsigned I = 0, N = Record.size(); I != N; ++I)\r
- UnusedFileScopedDecls.push_back(getGlobalDeclID(F, Record[I]));\r
- break;\r
-\r
- case DELEGATING_CTORS:\r
- for (unsigned I = 0, N = Record.size(); I != N; ++I)\r
- DelegatingCtorDecls.push_back(getGlobalDeclID(F, Record[I]));\r
- break;\r
-\r
- case WEAK_UNDECLARED_IDENTIFIERS:\r
- if (Record.size() % 4 != 0) {\r
- Error("invalid weak identifiers record");\r
- return true;\r
- }\r
- \r
- // FIXME: Ignore weak undeclared identifiers from non-original PCH \r
- // files. This isn't the way to do it :)\r
- WeakUndeclaredIdentifiers.clear();\r
- \r
- // Translate the weak, undeclared identifiers into global IDs.\r
- for (unsigned I = 0, N = Record.size(); I < N; /* in loop */) {\r
- WeakUndeclaredIdentifiers.push_back(\r
- getGlobalIdentifierID(F, Record[I++]));\r
- WeakUndeclaredIdentifiers.push_back(\r
- getGlobalIdentifierID(F, Record[I++]));\r
- WeakUndeclaredIdentifiers.push_back(\r
- ReadSourceLocation(F, Record, I).getRawEncoding());\r
- WeakUndeclaredIdentifiers.push_back(Record[I++]);\r
- }\r
- break;\r
-\r
- case LOCALLY_SCOPED_EXTERNAL_DECLS:\r
- for (unsigned I = 0, N = Record.size(); I != N; ++I)\r
- LocallyScopedExternalDecls.push_back(getGlobalDeclID(F, Record[I]));\r
- break;\r
-\r
- case SELECTOR_OFFSETS: {\r
- F.SelectorOffsets = (const uint32_t *)BlobStart;\r
- F.LocalNumSelectors = Record[0];\r
- unsigned LocalBaseSelectorID = Record[1];\r
- F.BaseSelectorID = getTotalNumSelectors();\r
- \r
- if (F.LocalNumSelectors > 0) {\r
- // Introduce the global -> local mapping for selectors within this \r
- // module.\r
- GlobalSelectorMap.insert(std::make_pair(getTotalNumSelectors()+1, &F));\r
- \r
- // Introduce the local -> global mapping for selectors within this \r
- // module.\r
- F.SelectorRemap.insertOrReplace(\r
- std::make_pair(LocalBaseSelectorID,\r
- F.BaseSelectorID - LocalBaseSelectorID));\r
-\r
- SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors); \r
- }\r
- break;\r
- }\r
- \r
- case METHOD_POOL:\r
- F.SelectorLookupTableData = (const unsigned char *)BlobStart;\r
- if (Record[0])\r
- F.SelectorLookupTable\r
- = ASTSelectorLookupTable::Create(\r
- F.SelectorLookupTableData + Record[0],\r
- F.SelectorLookupTableData,\r
- ASTSelectorLookupTrait(*this, F));\r
- TotalNumMethodPoolEntries += Record[1];\r
- break;\r
-\r
- case REFERENCED_SELECTOR_POOL:\r
- if (!Record.empty()) {\r
- for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) {\r
- ReferencedSelectorsData.push_back(getGlobalSelectorID(F, \r
- Record[Idx++]));\r
- ReferencedSelectorsData.push_back(ReadSourceLocation(F, Record, Idx).\r
- getRawEncoding());\r
- }\r
- }\r
- break;\r
-\r
- case PP_COUNTER_VALUE:\r
- if (!Record.empty() && Listener)\r
- Listener->ReadCounter(F, Record[0]);\r
- break;\r
- \r
- case FILE_SORTED_DECLS:\r
- F.FileSortedDecls = (const DeclID *)BlobStart;\r
- F.NumFileSortedDecls = Record[0];\r
- break;\r
-\r
- case SOURCE_LOCATION_OFFSETS: {\r
- F.SLocEntryOffsets = (const uint32_t *)BlobStart;\r
- F.LocalNumSLocEntries = Record[0];\r
- unsigned SLocSpaceSize = Record[1];\r
- llvm::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) =\r
- SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries,\r
- SLocSpaceSize);\r
- // Make our entry in the range map. BaseID is negative and growing, so\r
- // we invert it. Because we invert it, though, we need the other end of\r
- // the range.\r
- unsigned RangeStart =\r
- unsigned(-F.SLocEntryBaseID) - F.LocalNumSLocEntries + 1;\r
- GlobalSLocEntryMap.insert(std::make_pair(RangeStart, &F));\r
- F.FirstLoc = SourceLocation::getFromRawEncoding(F.SLocEntryBaseOffset);\r
-\r
- // SLocEntryBaseOffset is lower than MaxLoadedOffset and decreasing.\r
- assert((F.SLocEntryBaseOffset & (1U << 31U)) == 0);\r
- GlobalSLocOffsetMap.insert(\r
- std::make_pair(SourceManager::MaxLoadedOffset - F.SLocEntryBaseOffset\r
- - SLocSpaceSize,&F));\r
-\r
- // Initialize the remapping table.\r
- // Invalid stays invalid.\r
- F.SLocRemap.insert(std::make_pair(0U, 0));\r
- // This module. Base was 2 when being compiled.\r
- F.SLocRemap.insert(std::make_pair(2U,\r
- static_cast<int>(F.SLocEntryBaseOffset - 2)));\r
- \r
- TotalNumSLocEntries += F.LocalNumSLocEntries;\r
- break;\r
- }\r
-\r
- case MODULE_OFFSET_MAP: {\r
- // Additional remapping information.\r
- const unsigned char *Data = (const unsigned char*)BlobStart;\r
- const unsigned char *DataEnd = Data + BlobLen;\r
- \r
- // Continuous range maps we may be updating in our module.\r
- ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap);\r
- ContinuousRangeMap<uint32_t, int, 2>::Builder \r
- IdentifierRemap(F.IdentifierRemap);\r
- ContinuousRangeMap<uint32_t, int, 2>::Builder\r
- MacroRemap(F.MacroRemap);\r
- ContinuousRangeMap<uint32_t, int, 2>::Builder\r
- PreprocessedEntityRemap(F.PreprocessedEntityRemap);\r
- ContinuousRangeMap<uint32_t, int, 2>::Builder \r
- SubmoduleRemap(F.SubmoduleRemap);\r
- ContinuousRangeMap<uint32_t, int, 2>::Builder \r
- SelectorRemap(F.SelectorRemap);\r
- ContinuousRangeMap<uint32_t, int, 2>::Builder DeclRemap(F.DeclRemap);\r
- ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap);\r
-\r
- while(Data < DataEnd) {\r
- uint16_t Len = io::ReadUnalignedLE16(Data);\r
- StringRef Name = StringRef((const char*)Data, Len);\r
- Data += Len;\r
- ModuleFile *OM = ModuleMgr.lookup(Name);\r
- if (!OM) {\r
- Error("SourceLocation remap refers to unknown module");\r
- return true;\r
- }\r
-\r
- uint32_t SLocOffset = io::ReadUnalignedLE32(Data);\r
- uint32_t IdentifierIDOffset = io::ReadUnalignedLE32(Data);\r
- uint32_t MacroIDOffset = io::ReadUnalignedLE32(Data);\r
- uint32_t PreprocessedEntityIDOffset = io::ReadUnalignedLE32(Data);\r
- uint32_t SubmoduleIDOffset = io::ReadUnalignedLE32(Data);\r
- uint32_t SelectorIDOffset = io::ReadUnalignedLE32(Data);\r
- uint32_t DeclIDOffset = io::ReadUnalignedLE32(Data);\r
- uint32_t TypeIndexOffset = io::ReadUnalignedLE32(Data);\r
- \r
- // Source location offset is mapped to OM->SLocEntryBaseOffset.\r
- SLocRemap.insert(std::make_pair(SLocOffset,\r
- static_cast<int>(OM->SLocEntryBaseOffset - SLocOffset)));\r
- IdentifierRemap.insert(\r
- std::make_pair(IdentifierIDOffset, \r
- OM->BaseIdentifierID - IdentifierIDOffset));\r
- MacroRemap.insert(std::make_pair(MacroIDOffset,\r
- OM->BaseMacroID - MacroIDOffset));\r
- PreprocessedEntityRemap.insert(\r
- std::make_pair(PreprocessedEntityIDOffset, \r
- OM->BasePreprocessedEntityID - PreprocessedEntityIDOffset));\r
- SubmoduleRemap.insert(std::make_pair(SubmoduleIDOffset, \r
- OM->BaseSubmoduleID - SubmoduleIDOffset));\r
- SelectorRemap.insert(std::make_pair(SelectorIDOffset, \r
- OM->BaseSelectorID - SelectorIDOffset));\r
- DeclRemap.insert(std::make_pair(DeclIDOffset, \r
- OM->BaseDeclID - DeclIDOffset));\r
- \r
- TypeRemap.insert(std::make_pair(TypeIndexOffset, \r
- OM->BaseTypeIndex - TypeIndexOffset));\r
-\r
- // Global -> local mappings.\r
- F.GlobalToLocalDeclIDs[OM] = DeclIDOffset;\r
- }\r
- break;\r
- }\r
-\r
- case SOURCE_MANAGER_LINE_TABLE:\r
- if (ParseLineTable(F, Record))\r
- return true;\r
- break;\r
-\r
- case SOURCE_LOCATION_PRELOADS: {\r
- // Need to transform from the local view (1-based IDs) to the global view,\r
- // which is based off F.SLocEntryBaseID.\r
- if (!F.PreloadSLocEntries.empty()) {\r
- Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file");\r
- return true;\r
- }\r
- \r
- F.PreloadSLocEntries.swap(Record);\r
- break;\r
- }\r
-\r
- case EXT_VECTOR_DECLS:\r
- for (unsigned I = 0, N = Record.size(); I != N; ++I)\r
- ExtVectorDecls.push_back(getGlobalDeclID(F, Record[I]));\r
- break;\r
-\r
- case VTABLE_USES:\r
- if (Record.size() % 3 != 0) {\r
- Error("Invalid VTABLE_USES record");\r
- return true;\r
- }\r
- \r
- // Later tables overwrite earlier ones.\r
- // FIXME: Modules will have some trouble with this. This is clearly not\r
- // the right way to do this.\r
- VTableUses.clear();\r
- \r
- for (unsigned Idx = 0, N = Record.size(); Idx != N; /* In loop */) {\r
- VTableUses.push_back(getGlobalDeclID(F, Record[Idx++]));\r
- VTableUses.push_back(\r
- ReadSourceLocation(F, Record, Idx).getRawEncoding());\r
- VTableUses.push_back(Record[Idx++]);\r
- }\r
- break;\r
-\r
- case DYNAMIC_CLASSES:\r
- for (unsigned I = 0, N = Record.size(); I != N; ++I)\r
- DynamicClasses.push_back(getGlobalDeclID(F, Record[I]));\r
- break;\r
-\r
- case PENDING_IMPLICIT_INSTANTIATIONS:\r
- if (PendingInstantiations.size() % 2 != 0) {\r
- Error("Invalid existing PendingInstantiations");\r
- return true;\r
- }\r
-\r
- if (Record.size() % 2 != 0) {\r
- Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block");\r
- return true;\r
- }\r
-\r
- for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {\r
- PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++]));\r
- PendingInstantiations.push_back(\r
- ReadSourceLocation(F, Record, I).getRawEncoding());\r
- }\r
- break;\r
-\r
- case SEMA_DECL_REFS:\r
- // Later tables overwrite earlier ones.\r
- // FIXME: Modules will have some trouble with this.\r
- SemaDeclRefs.clear();\r
- for (unsigned I = 0, N = Record.size(); I != N; ++I)\r
- SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I]));\r
- break;\r
-\r
- case PPD_ENTITIES_OFFSETS: {\r
- F.PreprocessedEntityOffsets = (const PPEntityOffset *)BlobStart;\r
- assert(BlobLen % sizeof(PPEntityOffset) == 0);\r
- F.NumPreprocessedEntities = BlobLen / sizeof(PPEntityOffset);\r
-\r
- unsigned LocalBasePreprocessedEntityID = Record[0];\r
- \r
- unsigned StartingID;\r
- if (!PP.getPreprocessingRecord())\r
- PP.createPreprocessingRecord();\r
- if (!PP.getPreprocessingRecord()->getExternalSource())\r
- PP.getPreprocessingRecord()->SetExternalSource(*this);\r
- StartingID \r
- = PP.getPreprocessingRecord()\r
- ->allocateLoadedEntities(F.NumPreprocessedEntities);\r
- F.BasePreprocessedEntityID = StartingID;\r
-\r
- if (F.NumPreprocessedEntities > 0) {\r
- // Introduce the global -> local mapping for preprocessed entities in\r
- // this module.\r
- GlobalPreprocessedEntityMap.insert(std::make_pair(StartingID, &F));\r
- \r
- // Introduce the local -> global mapping for preprocessed entities in\r
- // this module.\r
- F.PreprocessedEntityRemap.insertOrReplace(\r
- std::make_pair(LocalBasePreprocessedEntityID,\r
- F.BasePreprocessedEntityID - LocalBasePreprocessedEntityID));\r
- }\r
-\r
- break;\r
- }\r
- \r
- case DECL_UPDATE_OFFSETS: {\r
- if (Record.size() % 2 != 0) {\r
- Error("invalid DECL_UPDATE_OFFSETS block in AST file");\r
- return true;\r
- }\r
- for (unsigned I = 0, N = Record.size(); I != N; I += 2)\r
- DeclUpdateOffsets[getGlobalDeclID(F, Record[I])]\r
- .push_back(std::make_pair(&F, Record[I+1]));\r
- break;\r
- }\r
-\r
- case DECL_REPLACEMENTS: {\r
- if (Record.size() % 3 != 0) {\r
- Error("invalid DECL_REPLACEMENTS block in AST file");\r
- return true;\r
- }\r
- for (unsigned I = 0, N = Record.size(); I != N; I += 3)\r
- ReplacedDecls[getGlobalDeclID(F, Record[I])]\r
- = ReplacedDeclInfo(&F, Record[I+1], Record[I+2]);\r
- break;\r
- }\r
-\r
- case OBJC_CATEGORIES_MAP: {\r
- if (F.LocalNumObjCCategoriesInMap != 0) {\r
- Error("duplicate OBJC_CATEGORIES_MAP record in AST file");\r
- return true;\r
- }\r
- \r
- F.LocalNumObjCCategoriesInMap = Record[0];\r
- F.ObjCCategoriesMap = (const ObjCCategoriesInfo *)BlobStart;\r
- break;\r
- }\r
- \r
- case OBJC_CATEGORIES:\r
- F.ObjCCategories.swap(Record);\r
- break;\r
- \r
- case CXX_BASE_SPECIFIER_OFFSETS: {\r
- if (F.LocalNumCXXBaseSpecifiers != 0) {\r
- Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file");\r
- return true;\r
- }\r
- \r
- F.LocalNumCXXBaseSpecifiers = Record[0];\r
- F.CXXBaseSpecifiersOffsets = (const uint32_t *)BlobStart;\r
- NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers;\r
- break;\r
- }\r
-\r
- case DIAG_PRAGMA_MAPPINGS:\r
- if (F.PragmaDiagMappings.empty())\r
- F.PragmaDiagMappings.swap(Record);\r
- else\r
- F.PragmaDiagMappings.insert(F.PragmaDiagMappings.end(),\r
- Record.begin(), Record.end());\r
- break;\r
- \r
- case CUDA_SPECIAL_DECL_REFS:\r
- // Later tables overwrite earlier ones.\r
- // FIXME: Modules will have trouble with this.\r
- CUDASpecialDeclRefs.clear();\r
- for (unsigned I = 0, N = Record.size(); I != N; ++I)\r
- CUDASpecialDeclRefs.push_back(getGlobalDeclID(F, Record[I]));\r
- break;\r
-\r
- case HEADER_SEARCH_TABLE: {\r
- F.HeaderFileInfoTableData = BlobStart;\r
- F.LocalNumHeaderFileInfos = Record[1];\r
- F.HeaderFileFrameworkStrings = BlobStart + Record[2];\r
- if (Record[0]) {\r
- F.HeaderFileInfoTable\r
- = HeaderFileInfoLookupTable::Create(\r
- (const unsigned char *)F.HeaderFileInfoTableData + Record[0],\r
- (const unsigned char *)F.HeaderFileInfoTableData,\r
- HeaderFileInfoTrait(*this, F, \r
- &PP.getHeaderSearchInfo(),\r
- BlobStart + Record[2]));\r
- \r
- PP.getHeaderSearchInfo().SetExternalSource(this);\r
- if (!PP.getHeaderSearchInfo().getExternalLookup())\r
- PP.getHeaderSearchInfo().SetExternalLookup(this);\r
- }\r
- break;\r
- }\r
- \r
- case FP_PRAGMA_OPTIONS:\r
- // Later tables overwrite earlier ones.\r
- FPPragmaOptions.swap(Record);\r
- break;\r
-\r
- case OPENCL_EXTENSIONS:\r
- // Later tables overwrite earlier ones.\r
- OpenCLExtensions.swap(Record);\r
- break;\r
-\r
- case TENTATIVE_DEFINITIONS:\r
- for (unsigned I = 0, N = Record.size(); I != N; ++I)\r
- TentativeDefinitions.push_back(getGlobalDeclID(F, Record[I]));\r
- break;\r
- \r
- case KNOWN_NAMESPACES:\r
- for (unsigned I = 0, N = Record.size(); I != N; ++I)\r
- KnownNamespaces.push_back(getGlobalDeclID(F, Record[I]));\r
- break;\r
- \r
- case IMPORTED_MODULES: {\r
- if (F.Kind != MK_Module) {\r
- // If we aren't loading a module (which has its own exports), make\r
- // all of the imported modules visible.\r
- // FIXME: Deal with macros-only imports.\r
- for (unsigned I = 0, N = Record.size(); I != N; ++I) {\r
- if (unsigned GlobalID = getGlobalSubmoduleID(F, Record[I]))\r
- ImportedModules.push_back(GlobalID);\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case LOCAL_REDECLARATIONS: {\r
- F.RedeclarationChains.swap(Record);\r
- break;\r
- }\r
- \r
- case LOCAL_REDECLARATIONS_MAP: {\r
- if (F.LocalNumRedeclarationsInMap != 0) {\r
- Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file");\r
- return true;\r
- }\r
- \r
- F.LocalNumRedeclarationsInMap = Record[0];\r
- F.RedeclarationsMap = (const LocalRedeclarationsInfo *)BlobStart;\r
- break;\r
- }\r
- \r
- case MERGED_DECLARATIONS: {\r
- for (unsigned Idx = 0; Idx < Record.size(); /* increment in loop */) {\r
- GlobalDeclID CanonID = getGlobalDeclID(F, Record[Idx++]);\r
- SmallVectorImpl<GlobalDeclID> &Decls = StoredMergedDecls[CanonID];\r
- for (unsigned N = Record[Idx++]; N > 0; --N)\r
- Decls.push_back(getGlobalDeclID(F, Record[Idx++]));\r
- }\r
- break;\r
- }\r
-\r
- case MACRO_OFFSET: {\r
- if (F.LocalNumMacros != 0) {\r
- Error("duplicate MACRO_OFFSET record in AST file");\r
- return true;\r
- }\r
- F.MacroOffsets = (const uint32_t *)BlobStart;\r
- F.LocalNumMacros = Record[0];\r
- unsigned LocalBaseMacroID = Record[1];\r
- F.BaseMacroID = getTotalNumMacros();\r
-\r
- if (F.LocalNumMacros > 0) {\r
- // Introduce the global -> local mapping for macros within this module.\r
- GlobalMacroMap.insert(std::make_pair(getTotalNumMacros() + 1, &F));\r
-\r
- // Introduce the local -> global mapping for macros within this module.\r
- F.MacroRemap.insertOrReplace(\r
- std::make_pair(LocalBaseMacroID,\r
- F.BaseMacroID - LocalBaseMacroID));\r
-\r
- MacrosLoaded.resize(MacrosLoaded.size() + F.LocalNumMacros);\r
- }\r
- break;\r
- }\r
-\r
- case MACRO_UPDATES: {\r
- for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {\r
- MacroID ID = getGlobalMacroID(F, Record[I++]);\r
- if (I == N)\r
- break;\r
-\r
- SourceLocation UndefLoc = ReadSourceLocation(F, Record, I);\r
- SubmoduleID SubmoduleID = getGlobalSubmoduleID(F, Record[I++]);;\r
- MacroUpdate Update;\r
- Update.UndefLoc = UndefLoc;\r
- MacroUpdates[ID].push_back(std::make_pair(SubmoduleID, Update));\r
- }\r
- break;\r
- }\r
- }\r
- }\r
- Error("premature end of bitstream in AST file");\r
- return true;\r
-}\r
-\r
-void ASTReader::makeNamesVisible(const HiddenNames &Names) {\r
- for (unsigned I = 0, N = Names.size(); I != N; ++I) {\r
- switch (Names[I].getKind()) {\r
- case HiddenName::Declaration:\r
- Names[I].getDecl()->Hidden = false;\r
- break;\r
-\r
- case HiddenName::MacroVisibility: {\r
- std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();\r
- Macro.second->setHidden(!Macro.second->isPublic());\r
- if (Macro.second->isDefined()) {\r
- PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);\r
- }\r
- break;\r
- }\r
-\r
- case HiddenName::MacroUndef: {\r
- std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();\r
- if (Macro.second->isDefined()) {\r
- Macro.second->setUndefLoc(Names[I].getMacroUndefLoc());\r
- if (PPMutationListener *Listener = PP.getPPMutationListener())\r
- Listener->UndefinedMacro(Macro.second);\r
- PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);\r
- }\r
- break;\r
- }\r
- }\r
- }\r
-}\r
-\r
-void ASTReader::makeModuleVisible(Module *Mod, \r
- Module::NameVisibilityKind NameVisibility) {\r
- llvm::SmallPtrSet<Module *, 4> Visited;\r
- llvm::SmallVector<Module *, 4> Stack;\r
- Stack.push_back(Mod); \r
- while (!Stack.empty()) {\r
- Mod = Stack.back();\r
- Stack.pop_back();\r
-\r
- if (NameVisibility <= Mod->NameVisibility) {\r
- // This module already has this level of visibility (or greater), so \r
- // there is nothing more to do.\r
- continue;\r
- }\r
- \r
- if (!Mod->isAvailable()) {\r
- // Modules that aren't available cannot be made visible.\r
- continue;\r
- }\r
-\r
- // Update the module's name visibility.\r
- Mod->NameVisibility = NameVisibility;\r
- \r
- // If we've already deserialized any names from this module,\r
- // mark them as visible.\r
- HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod);\r
- if (Hidden != HiddenNamesMap.end()) {\r
- makeNamesVisible(Hidden->second);\r
- HiddenNamesMap.erase(Hidden);\r
- }\r
- \r
- // Push any non-explicit submodules onto the stack to be marked as\r
- // visible.\r
- for (Module::submodule_iterator Sub = Mod->submodule_begin(),\r
- SubEnd = Mod->submodule_end();\r
- Sub != SubEnd; ++Sub) {\r
- if (!(*Sub)->IsExplicit && Visited.insert(*Sub))\r
- Stack.push_back(*Sub);\r
- }\r
- \r
- // Push any exported modules onto the stack to be marked as visible.\r
- bool AnyWildcard = false;\r
- bool UnrestrictedWildcard = false;\r
- llvm::SmallVector<Module *, 4> WildcardRestrictions;\r
- for (unsigned I = 0, N = Mod->Exports.size(); I != N; ++I) {\r
- Module *Exported = Mod->Exports[I].getPointer();\r
- if (!Mod->Exports[I].getInt()) {\r
- // Export a named module directly; no wildcards involved.\r
- if (Visited.insert(Exported))\r
- Stack.push_back(Exported);\r
- \r
- continue;\r
- }\r
- \r
- // Wildcard export: export all of the imported modules that match\r
- // the given pattern.\r
- AnyWildcard = true;\r
- if (UnrestrictedWildcard)\r
- continue;\r
-\r
- if (Module *Restriction = Mod->Exports[I].getPointer())\r
- WildcardRestrictions.push_back(Restriction);\r
- else {\r
- WildcardRestrictions.clear();\r
- UnrestrictedWildcard = true;\r
- }\r
- }\r
- \r
- // If there were any wildcards, push any imported modules that were\r
- // re-exported by the wildcard restriction.\r
- if (!AnyWildcard)\r
- continue;\r
- \r
- for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) {\r
- Module *Imported = Mod->Imports[I];\r
- if (!Visited.insert(Imported))\r
- continue;\r
- \r
- bool Acceptable = UnrestrictedWildcard;\r
- if (!Acceptable) {\r
- // Check whether this module meets one of the restrictions.\r
- for (unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) {\r
- Module *Restriction = WildcardRestrictions[R];\r
- if (Imported == Restriction || Imported->isSubModuleOf(Restriction)) {\r
- Acceptable = true;\r
- break;\r
- }\r
- }\r
- }\r
- \r
- if (!Acceptable)\r
- continue;\r
- \r
- Stack.push_back(Imported);\r
- }\r
- }\r
-}\r
-\r
-ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,\r
- ModuleKind Type,\r
- SourceLocation ImportLoc,\r
- unsigned ClientLoadCapabilities) {\r
- // Bump the generation number.\r
- unsigned PreviousGeneration = CurrentGeneration++;\r
-\r
- unsigned NumModules = ModuleMgr.size();\r
- llvm::SmallVector<ImportedModule, 4> Loaded;\r
- switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc,\r
- /*ImportedBy=*/0, Loaded,\r
- ClientLoadCapabilities)) {\r
- case Failure:\r
- case OutOfDate:\r
- case VersionMismatch:\r
- case ConfigurationMismatch:\r
- case HadErrors:\r
- ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end());\r
- return ReadResult;\r
-\r
- case Success:\r
- break;\r
- }\r
-\r
- // Here comes stuff that we only do once the entire chain is loaded.\r
-\r
- // Load the AST blocks of all of the modules that we loaded.\r
- for (llvm::SmallVectorImpl<ImportedModule>::iterator M = Loaded.begin(),\r
- MEnd = Loaded.end();\r
- M != MEnd; ++M) {\r
- ModuleFile &F = *M->Mod;\r
-\r
- // Read the AST block.\r
- if (ReadASTBlock(F))\r
- return Failure;\r
-\r
- // Once read, set the ModuleFile bit base offset and update the size in \r
- // bits of all files we've seen.\r
- F.GlobalBitOffset = TotalModulesSizeInBits;\r
- TotalModulesSizeInBits += F.SizeInBits;\r
- GlobalBitOffsetsMap.insert(std::make_pair(F.GlobalBitOffset, &F));\r
- \r
- // Preload SLocEntries.\r
- for (unsigned I = 0, N = F.PreloadSLocEntries.size(); I != N; ++I) {\r
- int Index = int(F.PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID;\r
- // Load it through the SourceManager and don't call ReadSLocEntry()\r
- // directly because the entry may have already been loaded in which case\r
- // calling ReadSLocEntry() directly would trigger an assertion in\r
- // SourceManager.\r
- SourceMgr.getLoadedSLocEntryByID(Index);\r
- }\r
- }\r
-\r
- // Setup the import locations.\r
- for (llvm::SmallVectorImpl<ImportedModule>::iterator M = Loaded.begin(),\r
- MEnd = Loaded.end();\r
- M != MEnd; ++M) {\r
- ModuleFile &F = *M->Mod;\r
- if (!M->ImportedBy)\r
- F.ImportLoc = M->ImportLoc;\r
- else\r
- F.ImportLoc = ReadSourceLocation(*M->ImportedBy,\r
- M->ImportLoc.getRawEncoding());\r
- }\r
-\r
- // Mark all of the identifiers in the identifier table as being out of date,\r
- // so that various accessors know to check the loaded modules when the\r
- // identifier is used.\r
- for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),\r
- IdEnd = PP.getIdentifierTable().end();\r
- Id != IdEnd; ++Id)\r
- Id->second->setOutOfDate(true);\r
- \r
- // Resolve any unresolved module exports.\r
- for (unsigned I = 0, N = UnresolvedModuleImportExports.size(); I != N; ++I) {\r
- UnresolvedModuleImportExport &Unresolved = UnresolvedModuleImportExports[I];\r
- SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,Unresolved.ID);\r
- Module *ResolvedMod = getSubmodule(GlobalID);\r
- \r
- if (Unresolved.IsImport) {\r
- if (ResolvedMod)\r
- Unresolved.Mod->Imports.push_back(ResolvedMod);\r
- continue;\r
- }\r
-\r
- if (ResolvedMod || Unresolved.IsWildcard)\r
- Unresolved.Mod->Exports.push_back(\r
- Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard));\r
- }\r
- UnresolvedModuleImportExports.clear();\r
- \r
- InitializeContext();\r
-\r
- if (DeserializationListener)\r
- DeserializationListener->ReaderInitialized(this);\r
-\r
- ModuleFile &PrimaryModule = ModuleMgr.getPrimaryModule();\r
- if (!PrimaryModule.OriginalSourceFileID.isInvalid()) {\r
- PrimaryModule.OriginalSourceFileID \r
- = FileID::get(PrimaryModule.SLocEntryBaseID\r
- + PrimaryModule.OriginalSourceFileID.getOpaqueValue() - 1);\r
-\r
- // If this AST file is a precompiled preamble, then set the\r
- // preamble file ID of the source manager to the file source file\r
- // from which the preamble was built.\r
- if (Type == MK_Preamble) {\r
- SourceMgr.setPreambleFileID(PrimaryModule.OriginalSourceFileID);\r
- } else if (Type == MK_MainFile) {\r
- SourceMgr.setMainFileID(PrimaryModule.OriginalSourceFileID);\r
- }\r
- }\r
- \r
- // For any Objective-C class definitions we have already loaded, make sure\r
- // that we load any additional categories.\r
- for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) {\r
- loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(), \r
- ObjCClassesLoaded[I],\r
- PreviousGeneration);\r
- }\r
- \r
- return Success;\r
-}\r
-\r
-ASTReader::ASTReadResult\r
-ASTReader::ReadASTCore(StringRef FileName,\r
- ModuleKind Type,\r
- SourceLocation ImportLoc,\r
- ModuleFile *ImportedBy,\r
- llvm::SmallVectorImpl<ImportedModule> &Loaded,\r
- unsigned ClientLoadCapabilities) {\r
- ModuleFile *M;\r
- bool NewModule;\r
- std::string ErrorStr;\r
- llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportLoc,\r
- ImportedBy, CurrentGeneration,\r
- ErrorStr);\r
-\r
- if (!M) {\r
- // We couldn't load the module.\r
- std::string Msg = "Unable to load module \"" + FileName.str() + "\": "\r
- + ErrorStr;\r
- Error(Msg);\r
- return Failure;\r
- }\r
-\r
- if (!NewModule) {\r
- // We've already loaded this module.\r
- return Success;\r
- }\r
-\r
- // FIXME: This seems rather a hack. Should CurrentDir be part of the\r
- // module?\r
- if (FileName != "-") {\r
- CurrentDir = llvm::sys::path::parent_path(FileName);\r
- if (CurrentDir.empty()) CurrentDir = ".";\r
- }\r
-\r
- ModuleFile &F = *M;\r
- llvm::BitstreamCursor &Stream = F.Stream;\r
- Stream.init(F.StreamFile);\r
- F.SizeInBits = F.Buffer->getBufferSize() * 8;\r
- \r
- // Sniff for the signature.\r
- if (Stream.Read(8) != 'C' ||\r
- Stream.Read(8) != 'P' ||\r
- Stream.Read(8) != 'C' ||\r
- Stream.Read(8) != 'H') {\r
- Diag(diag::err_not_a_pch_file) << FileName;\r
- return Failure;\r
- }\r
-\r
- // This is used for compatibility with older PCH formats.\r
- bool HaveReadControlBlock = false;\r
-\r
- while (!Stream.AtEndOfStream()) {\r
- unsigned Code = Stream.ReadCode();\r
-\r
- if (Code != llvm::bitc::ENTER_SUBBLOCK) {\r
- Error("invalid record at top-level of AST file");\r
- return Failure;\r
- }\r
-\r
- unsigned BlockID = Stream.ReadSubBlockID();\r
-\r
- // We only know the control subblock ID.\r
- switch (BlockID) {\r
- case llvm::bitc::BLOCKINFO_BLOCK_ID:\r
- if (Stream.ReadBlockInfoBlock()) {\r
- Error("malformed BlockInfoBlock in AST file");\r
- return Failure;\r
- }\r
- break;\r
- case CONTROL_BLOCK_ID:\r
- HaveReadControlBlock = true;\r
- switch (ReadControlBlock(F, Loaded, ClientLoadCapabilities)) {\r
- case Success:\r
- break;\r
-\r
- case Failure: return Failure;\r
- case OutOfDate: return OutOfDate;\r
- case VersionMismatch: return VersionMismatch;\r
- case ConfigurationMismatch: return ConfigurationMismatch;\r
- case HadErrors: return HadErrors;\r
- }\r
- break;\r
- case AST_BLOCK_ID:\r
- if (!HaveReadControlBlock) {\r
- if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)\r
- Diag(diag::warn_pch_version_too_old);\r
- return VersionMismatch;\r
- }\r
-\r
- // Record that we've loaded this module.\r
- Loaded.push_back(ImportedModule(M, ImportedBy, ImportLoc));\r
- return Success;\r
-\r
- default:\r
- if (Stream.SkipBlock()) {\r
- Error("malformed block record in AST file");\r
- return Failure;\r
- }\r
- break;\r
- }\r
- }\r
- \r
- return Success;\r
-}\r
-\r
-void ASTReader::InitializeContext() { \r
- // If there's a listener, notify them that we "read" the translation unit.\r
- if (DeserializationListener)\r
- DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID, \r
- Context.getTranslationUnitDecl());\r
-\r
- // Make sure we load the declaration update records for the translation unit,\r
- // if there are any.\r
- loadDeclUpdateRecords(PREDEF_DECL_TRANSLATION_UNIT_ID, \r
- Context.getTranslationUnitDecl());\r
- \r
- // FIXME: Find a better way to deal with collisions between these\r
- // built-in types. Right now, we just ignore the problem.\r
- \r
- // Load the special types.\r
- if (SpecialTypes.size() >= NumSpecialTypeIDs) {\r
- if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING]) {\r
- if (!Context.CFConstantStringTypeDecl)\r
- Context.setCFConstantStringType(GetType(String));\r
- }\r
- \r
- if (unsigned File = SpecialTypes[SPECIAL_TYPE_FILE]) {\r
- QualType FileType = GetType(File);\r
- if (FileType.isNull()) {\r
- Error("FILE type is NULL");\r
- return;\r
- }\r
- \r
- if (!Context.FILEDecl) {\r
- if (const TypedefType *Typedef = FileType->getAs<TypedefType>())\r
- Context.setFILEDecl(Typedef->getDecl());\r
- else {\r
- const TagType *Tag = FileType->getAs<TagType>();\r
- if (!Tag) {\r
- Error("Invalid FILE type in AST file");\r
- return;\r
- }\r
- Context.setFILEDecl(Tag->getDecl());\r
- }\r
- }\r
- }\r
- \r
- if (unsigned Jmp_buf = SpecialTypes[SPECIAL_TYPE_JMP_BUF]) {\r
- QualType Jmp_bufType = GetType(Jmp_buf);\r
- if (Jmp_bufType.isNull()) {\r
- Error("jmp_buf type is NULL");\r
- return;\r
- }\r
- \r
- if (!Context.jmp_bufDecl) {\r
- if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>())\r
- Context.setjmp_bufDecl(Typedef->getDecl());\r
- else {\r
- const TagType *Tag = Jmp_bufType->getAs<TagType>();\r
- if (!Tag) {\r
- Error("Invalid jmp_buf type in AST file");\r
- return;\r
- }\r
- Context.setjmp_bufDecl(Tag->getDecl());\r
- }\r
- }\r
- }\r
- \r
- if (unsigned Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_SIGJMP_BUF]) {\r
- QualType Sigjmp_bufType = GetType(Sigjmp_buf);\r
- if (Sigjmp_bufType.isNull()) {\r
- Error("sigjmp_buf type is NULL");\r
- return;\r
- }\r
- \r
- if (!Context.sigjmp_bufDecl) {\r
- if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>())\r
- Context.setsigjmp_bufDecl(Typedef->getDecl());\r
- else {\r
- const TagType *Tag = Sigjmp_bufType->getAs<TagType>();\r
- assert(Tag && "Invalid sigjmp_buf type in AST file");\r
- Context.setsigjmp_bufDecl(Tag->getDecl());\r
- }\r
- }\r
- }\r
-\r
- if (unsigned ObjCIdRedef\r
- = SpecialTypes[SPECIAL_TYPE_OBJC_ID_REDEFINITION]) {\r
- if (Context.ObjCIdRedefinitionType.isNull())\r
- Context.ObjCIdRedefinitionType = GetType(ObjCIdRedef);\r
- }\r
-\r
- if (unsigned ObjCClassRedef\r
- = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) {\r
- if (Context.ObjCClassRedefinitionType.isNull())\r
- Context.ObjCClassRedefinitionType = GetType(ObjCClassRedef);\r
- }\r
-\r
- if (unsigned ObjCSelRedef\r
- = SpecialTypes[SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) {\r
- if (Context.ObjCSelRedefinitionType.isNull())\r
- Context.ObjCSelRedefinitionType = GetType(ObjCSelRedef);\r
- }\r
-\r
- if (unsigned Ucontext_t = SpecialTypes[SPECIAL_TYPE_UCONTEXT_T]) {\r
- QualType Ucontext_tType = GetType(Ucontext_t);\r
- if (Ucontext_tType.isNull()) {\r
- Error("ucontext_t type is NULL");\r
- return;\r
- }\r
-\r
- if (!Context.ucontext_tDecl) {\r
- if (const TypedefType *Typedef = Ucontext_tType->getAs<TypedefType>())\r
- Context.setucontext_tDecl(Typedef->getDecl());\r
- else {\r
- const TagType *Tag = Ucontext_tType->getAs<TagType>();\r
- assert(Tag && "Invalid ucontext_t type in AST file");\r
- Context.setucontext_tDecl(Tag->getDecl());\r
- }\r
- }\r
- }\r
- }\r
- \r
- ReadPragmaDiagnosticMappings(Context.getDiagnostics());\r
-\r
- // If there were any CUDA special declarations, deserialize them.\r
- if (!CUDASpecialDeclRefs.empty()) {\r
- assert(CUDASpecialDeclRefs.size() == 1 && "More decl refs than expected!");\r
- Context.setcudaConfigureCallDecl(\r
- cast<FunctionDecl>(GetDecl(CUDASpecialDeclRefs[0])));\r
- }\r
- \r
- // Re-export any modules that were imported by a non-module AST file.\r
- for (unsigned I = 0, N = ImportedModules.size(); I != N; ++I) {\r
- if (Module *Imported = getSubmodule(ImportedModules[I]))\r
- makeModuleVisible(Imported, Module::AllVisible);\r
- }\r
- ImportedModules.clear();\r
-}\r
-\r
-void ASTReader::finalizeForWriting() {\r
- for (HiddenNamesMapType::iterator Hidden = HiddenNamesMap.begin(),\r
- HiddenEnd = HiddenNamesMap.end();\r
- Hidden != HiddenEnd; ++Hidden) {\r
- makeNamesVisible(Hidden->second);\r
- }\r
- HiddenNamesMap.clear();\r
-}\r
-\r
-/// \brief Retrieve the name of the original source file name\r
-/// directly from the AST file, without actually loading the AST\r
-/// file.\r
-std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,\r
- FileManager &FileMgr,\r
- DiagnosticsEngine &Diags) {\r
- // Open the AST file.\r
- std::string ErrStr;\r
- OwningPtr<llvm::MemoryBuffer> Buffer;\r
- Buffer.reset(FileMgr.getBufferForFile(ASTFileName, &ErrStr));\r
- if (!Buffer) {\r
- Diags.Report(diag::err_fe_unable_to_read_pch_file) << ASTFileName << ErrStr;\r
- return std::string();\r
- }\r
-\r
- // Initialize the stream\r
- llvm::BitstreamReader StreamFile;\r
- llvm::BitstreamCursor Stream;\r
- StreamFile.init((const unsigned char *)Buffer->getBufferStart(),\r
- (const unsigned char *)Buffer->getBufferEnd());\r
- Stream.init(StreamFile);\r
-\r
- // Sniff for the signature.\r
- if (Stream.Read(8) != 'C' ||\r
- Stream.Read(8) != 'P' ||\r
- Stream.Read(8) != 'C' ||\r
- Stream.Read(8) != 'H') {\r
- Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName;\r
- return std::string();\r
- }\r
-\r
- RecordData Record;\r
- while (!Stream.AtEndOfStream()) {\r
- unsigned Code = Stream.ReadCode();\r
-\r
- if (Code == llvm::bitc::ENTER_SUBBLOCK) {\r
- unsigned BlockID = Stream.ReadSubBlockID();\r
-\r
- // We only know the AST subblock ID.\r
- switch (BlockID) {\r
- case CONTROL_BLOCK_ID:\r
- if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {\r
- Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;\r
- return std::string();\r
- }\r
- break;\r
-\r
- default:\r
- if (Stream.SkipBlock()) {\r
- Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;\r
- return std::string();\r
- }\r
- break;\r
- }\r
- continue;\r
- }\r
-\r
- if (Code == llvm::bitc::END_BLOCK) {\r
- if (Stream.ReadBlockEnd()) {\r
- Diags.Report(diag::err_fe_pch_error_at_end_block) << ASTFileName;\r
- return std::string();\r
- }\r
- continue;\r
- }\r
-\r
- if (Code == llvm::bitc::DEFINE_ABBREV) {\r
- Stream.ReadAbbrevRecord();\r
- continue;\r
- }\r
-\r
- Record.clear();\r
- const char *BlobStart = 0;\r
- unsigned BlobLen = 0;\r
- if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen) == ORIGINAL_FILE)\r
- return std::string(BlobStart, BlobLen);\r
- }\r
-\r
- return std::string();\r
-}\r
-\r
-namespace {\r
- class SimplePCHValidator : public ASTReaderListener {\r
- const LangOptions &ExistingLangOpts;\r
- const TargetOptions &ExistingTargetOpts;\r
- const PreprocessorOptions &ExistingPPOpts;\r
- FileManager &FileMgr;\r
- \r
- public:\r
- SimplePCHValidator(const LangOptions &ExistingLangOpts,\r
- const TargetOptions &ExistingTargetOpts,\r
- const PreprocessorOptions &ExistingPPOpts,\r
- FileManager &FileMgr)\r
- : ExistingLangOpts(ExistingLangOpts),\r
- ExistingTargetOpts(ExistingTargetOpts),\r
- ExistingPPOpts(ExistingPPOpts),\r
- FileMgr(FileMgr)\r
- {\r
- }\r
-\r
- virtual bool ReadLanguageOptions(const LangOptions &LangOpts,\r
- bool Complain) {\r
- return checkLanguageOptions(ExistingLangOpts, LangOpts, 0);\r
- }\r
- virtual bool ReadTargetOptions(const TargetOptions &TargetOpts,\r
- bool Complain) {\r
- return checkTargetOptions(ExistingTargetOpts, TargetOpts, 0);\r
- }\r
- virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,\r
- bool Complain,\r
- std::string &SuggestedPredefines) {\r
- return checkPreprocessorOptions(ExistingPPOpts, PPOpts, 0, FileMgr,\r
- SuggestedPredefines);\r
- }\r
- };\r
-}\r
-\r
-bool ASTReader::readASTFileControlBlock(StringRef Filename,\r
- FileManager &FileMgr,\r
- ASTReaderListener &Listener) {\r
- // Open the AST file.\r
- std::string ErrStr;\r
- OwningPtr<llvm::MemoryBuffer> Buffer;\r
- Buffer.reset(FileMgr.getBufferForFile(Filename, &ErrStr));\r
- if (!Buffer) {\r
- return true;\r
- }\r
-\r
- // Initialize the stream\r
- llvm::BitstreamReader StreamFile;\r
- llvm::BitstreamCursor Stream;\r
- StreamFile.init((const unsigned char *)Buffer->getBufferStart(),\r
- (const unsigned char *)Buffer->getBufferEnd());\r
- Stream.init(StreamFile);\r
-\r
- // Sniff for the signature.\r
- if (Stream.Read(8) != 'C' ||\r
- Stream.Read(8) != 'P' ||\r
- Stream.Read(8) != 'C' ||\r
- Stream.Read(8) != 'H') {\r
- return true;\r
- }\r
-\r
- RecordData Record;\r
- bool InControlBlock = false;\r
- while (!Stream.AtEndOfStream()) {\r
- unsigned Code = Stream.ReadCode();\r
-\r
- if (Code == llvm::bitc::ENTER_SUBBLOCK) {\r
- unsigned BlockID = Stream.ReadSubBlockID();\r
-\r
- // We only know the control subblock ID.\r
- switch (BlockID) {\r
- case CONTROL_BLOCK_ID:\r
- if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {\r
- return true;\r
- } else {\r
- InControlBlock = true;\r
- }\r
- break;\r
-\r
- default:\r
- if (Stream.SkipBlock())\r
- return true;\r
- break;\r
- }\r
- continue;\r
- }\r
-\r
- if (Code == llvm::bitc::END_BLOCK) {\r
- if (Stream.ReadBlockEnd()) {\r
- return true;\r
- }\r
-\r
- InControlBlock = false;\r
- continue;\r
- }\r
-\r
- if (Code == llvm::bitc::DEFINE_ABBREV) {\r
- Stream.ReadAbbrevRecord();\r
- continue;\r
- }\r
-\r
- Record.clear();\r
- const char *BlobStart = 0;\r
- unsigned BlobLen = 0;\r
- unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);\r
- if (InControlBlock) {\r
- switch ((ControlRecordTypes)RecCode) {\r
- case METADATA: {\r
- if (Record[0] != VERSION_MAJOR) {\r
- return true;\r
- }\r
-\r
- const std::string &CurBranch = getClangFullRepositoryVersion();\r
- StringRef ASTBranch(BlobStart, BlobLen);\r
- if (StringRef(CurBranch) != ASTBranch)\r
- return true;\r
-\r
- break;\r
- }\r
- case LANGUAGE_OPTIONS:\r
- if (ParseLanguageOptions(Record, false, Listener))\r
- return true;\r
- break;\r
-\r
- case TARGET_OPTIONS:\r
- if (ParseTargetOptions(Record, false, Listener))\r
- return true;\r
- break;\r
-\r
- case DIAGNOSTIC_OPTIONS:\r
- if (ParseDiagnosticOptions(Record, false, Listener))\r
- return true;\r
- break;\r
-\r
- case FILE_SYSTEM_OPTIONS:\r
- if (ParseFileSystemOptions(Record, false, Listener))\r
- return true;\r
- break;\r
-\r
- case HEADER_SEARCH_OPTIONS:\r
- if (ParseHeaderSearchOptions(Record, false, Listener))\r
- return true;\r
- break;\r
-\r
- case PREPROCESSOR_OPTIONS: {\r
- std::string IgnoredSuggestedPredefines;\r
- if (ParsePreprocessorOptions(Record, false, Listener,\r
- IgnoredSuggestedPredefines))\r
- return true;\r
- break;\r
- }\r
-\r
- default:\r
- // No other validation to perform.\r
- break;\r
- }\r
- }\r
- }\r
- \r
- return false;\r
-}\r
-\r
-\r
-bool ASTReader::isAcceptableASTFile(StringRef Filename,\r
- FileManager &FileMgr,\r
- const LangOptions &LangOpts,\r
- const TargetOptions &TargetOpts,\r
- const PreprocessorOptions &PPOpts) {\r
- SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, FileMgr);\r
- return !readASTFileControlBlock(Filename, FileMgr, validator);\r
-}\r
-\r
-bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {\r
- // Enter the submodule block.\r
- if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) {\r
- Error("malformed submodule block record in AST file");\r
- return true;\r
- }\r
-\r
- ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();\r
- bool First = true;\r
- Module *CurrentModule = 0;\r
- RecordData Record;\r
- while (true) {\r
- unsigned Code = F.Stream.ReadCode();\r
- if (Code == llvm::bitc::END_BLOCK) {\r
- if (F.Stream.ReadBlockEnd()) {\r
- Error("error at end of submodule block in AST file");\r
- return true;\r
- }\r
- return false;\r
- }\r
- \r
- if (Code == llvm::bitc::ENTER_SUBBLOCK) {\r
- // No known subblocks, always skip them.\r
- F.Stream.ReadSubBlockID();\r
- if (F.Stream.SkipBlock()) {\r
- Error("malformed block record in AST file");\r
- return true;\r
- }\r
- continue;\r
- }\r
- \r
- if (Code == llvm::bitc::DEFINE_ABBREV) {\r
- F.Stream.ReadAbbrevRecord();\r
- continue;\r
- }\r
- \r
- // Read a record.\r
- const char *BlobStart;\r
- unsigned BlobLen;\r
- Record.clear();\r
- switch (F.Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {\r
- default: // Default behavior: ignore.\r
- break;\r
- \r
- case SUBMODULE_DEFINITION: {\r
- if (First) {\r
- Error("missing submodule metadata record at beginning of block");\r
- return true;\r
- }\r
-\r
- if (Record.size() < 7) {\r
- Error("malformed module definition");\r
- return true;\r
- }\r
- \r
- StringRef Name(BlobStart, BlobLen);\r
- SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[0]);\r
- SubmoduleID Parent = getGlobalSubmoduleID(F, Record[1]);\r
- bool IsFramework = Record[2];\r
- bool IsExplicit = Record[3];\r
- bool IsSystem = Record[4];\r
- bool InferSubmodules = Record[5];\r
- bool InferExplicitSubmodules = Record[6];\r
- bool InferExportWildcard = Record[7];\r
- \r
- Module *ParentModule = 0;\r
- if (Parent)\r
- ParentModule = getSubmodule(Parent);\r
- \r
- // Retrieve this (sub)module from the module map, creating it if\r
- // necessary.\r
- CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, \r
- IsFramework, \r
- IsExplicit).first;\r
- SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS;\r
- if (GlobalIndex >= SubmodulesLoaded.size() ||\r
- SubmodulesLoaded[GlobalIndex]) {\r
- Error("too many submodules");\r
- return true;\r
- }\r
- \r
- CurrentModule->setASTFile(F.File);\r
- CurrentModule->IsFromModuleFile = true;\r
- CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;\r
- CurrentModule->InferSubmodules = InferSubmodules;\r
- CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;\r
- CurrentModule->InferExportWildcard = InferExportWildcard;\r
- if (DeserializationListener)\r
- DeserializationListener->ModuleRead(GlobalID, CurrentModule);\r
- \r
- SubmodulesLoaded[GlobalIndex] = CurrentModule;\r
- break;\r
- }\r
- \r
- case SUBMODULE_UMBRELLA_HEADER: {\r
- if (First) {\r
- Error("missing submodule metadata record at beginning of block");\r
- return true;\r
- }\r
-\r
- if (!CurrentModule)\r
- break;\r
- \r
- StringRef FileName(BlobStart, BlobLen);\r
- if (const FileEntry *Umbrella = PP.getFileManager().getFile(FileName)) {\r
- if (!CurrentModule->getUmbrellaHeader())\r
- ModMap.setUmbrellaHeader(CurrentModule, Umbrella);\r
- else if (CurrentModule->getUmbrellaHeader() != Umbrella) {\r
- Error("mismatched umbrella headers in submodule");\r
- return true;\r
- }\r
- }\r
- break;\r
- }\r
- \r
- case SUBMODULE_HEADER: {\r
- if (First) {\r
- Error("missing submodule metadata record at beginning of block");\r
- return true;\r
- }\r
-\r
- if (!CurrentModule)\r
- break;\r
- \r
- // FIXME: Be more lazy about this!\r
- StringRef FileName(BlobStart, BlobLen);\r
- if (const FileEntry *File = PP.getFileManager().getFile(FileName)) {\r
- if (std::find(CurrentModule->Headers.begin(), \r
- CurrentModule->Headers.end(), \r
- File) == CurrentModule->Headers.end())\r
- ModMap.addHeader(CurrentModule, File, false);\r
- }\r
- break; \r
- }\r
-\r
- case SUBMODULE_EXCLUDED_HEADER: {\r
- if (First) {\r
- Error("missing submodule metadata record at beginning of block");\r
- return true;\r
- }\r
-\r
- if (!CurrentModule)\r
- break;\r
- \r
- // FIXME: Be more lazy about this!\r
- StringRef FileName(BlobStart, BlobLen);\r
- if (const FileEntry *File = PP.getFileManager().getFile(FileName)) {\r
- if (std::find(CurrentModule->Headers.begin(), \r
- CurrentModule->Headers.end(), \r
- File) == CurrentModule->Headers.end())\r
- ModMap.addHeader(CurrentModule, File, true);\r
- }\r
- break; \r
- }\r
-\r
- case SUBMODULE_TOPHEADER: {\r
- if (First) {\r
- Error("missing submodule metadata record at beginning of block");\r
- return true;\r
- }\r
-\r
- if (!CurrentModule)\r
- break;\r
-\r
- // FIXME: Be more lazy about this!\r
- StringRef FileName(BlobStart, BlobLen);\r
- if (const FileEntry *File = PP.getFileManager().getFile(FileName))\r
- CurrentModule->TopHeaders.insert(File);\r
- break;\r
- }\r
-\r
- case SUBMODULE_UMBRELLA_DIR: {\r
- if (First) {\r
- Error("missing submodule metadata record at beginning of block");\r
- return true;\r
- }\r
- \r
- if (!CurrentModule)\r
- break;\r
- \r
- StringRef DirName(BlobStart, BlobLen);\r
- if (const DirectoryEntry *Umbrella\r
- = PP.getFileManager().getDirectory(DirName)) {\r
- if (!CurrentModule->getUmbrellaDir())\r
- ModMap.setUmbrellaDir(CurrentModule, Umbrella);\r
- else if (CurrentModule->getUmbrellaDir() != Umbrella) {\r
- Error("mismatched umbrella directories in submodule");\r
- return true;\r
- }\r
- }\r
- break;\r
- }\r
- \r
- case SUBMODULE_METADATA: {\r
- if (!First) {\r
- Error("submodule metadata record not at beginning of block");\r
- return true;\r
- }\r
- First = false;\r
- \r
- F.BaseSubmoduleID = getTotalNumSubmodules();\r
- F.LocalNumSubmodules = Record[0];\r
- unsigned LocalBaseSubmoduleID = Record[1];\r
- if (F.LocalNumSubmodules > 0) {\r
- // Introduce the global -> local mapping for submodules within this \r
- // module.\r
- GlobalSubmoduleMap.insert(std::make_pair(getTotalNumSubmodules()+1,&F));\r
- \r
- // Introduce the local -> global mapping for submodules within this \r
- // module.\r
- F.SubmoduleRemap.insertOrReplace(\r
- std::make_pair(LocalBaseSubmoduleID,\r
- F.BaseSubmoduleID - LocalBaseSubmoduleID));\r
- \r
- SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules);\r
- } \r
- break;\r
- }\r
- \r
- case SUBMODULE_IMPORTS: {\r
- if (First) {\r
- Error("missing submodule metadata record at beginning of block");\r
- return true;\r
- }\r
- \r
- if (!CurrentModule)\r
- break;\r
- \r
- for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {\r
- UnresolvedModuleImportExport Unresolved;\r
- Unresolved.File = &F;\r
- Unresolved.Mod = CurrentModule;\r
- Unresolved.ID = Record[Idx];\r
- Unresolved.IsImport = true;\r
- Unresolved.IsWildcard = false;\r
- UnresolvedModuleImportExports.push_back(Unresolved);\r
- }\r
- break;\r
- }\r
-\r
- case SUBMODULE_EXPORTS: {\r
- if (First) {\r
- Error("missing submodule metadata record at beginning of block");\r
- return true;\r
- }\r
- \r
- if (!CurrentModule)\r
- break;\r
- \r
- for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {\r
- UnresolvedModuleImportExport Unresolved;\r
- Unresolved.File = &F;\r
- Unresolved.Mod = CurrentModule;\r
- Unresolved.ID = Record[Idx];\r
- Unresolved.IsImport = false;\r
- Unresolved.IsWildcard = Record[Idx + 1];\r
- UnresolvedModuleImportExports.push_back(Unresolved);\r
- }\r
- \r
- // Once we've loaded the set of exports, there's no reason to keep \r
- // the parsed, unresolved exports around.\r
- CurrentModule->UnresolvedExports.clear();\r
- break;\r
- }\r
- case SUBMODULE_REQUIRES: {\r
- if (First) {\r
- Error("missing submodule metadata record at beginning of block");\r
- return true;\r
- }\r
-\r
- if (!CurrentModule)\r
- break;\r
-\r
- CurrentModule->addRequirement(StringRef(BlobStart, BlobLen), \r
- Context.getLangOpts(),\r
- Context.getTargetInfo());\r
- break;\r
- }\r
- }\r
- }\r
-}\r
-\r
-/// \brief Parse the record that corresponds to a LangOptions data\r
-/// structure.\r
-///\r
-/// This routine parses the language options from the AST file and then gives\r
-/// them to the AST listener if one is set.\r
-///\r
-/// \returns true if the listener deems the file unacceptable, false otherwise.\r
-bool ASTReader::ParseLanguageOptions(const RecordData &Record,\r
- bool Complain,\r
- ASTReaderListener &Listener) {\r
- LangOptions LangOpts;\r
- unsigned Idx = 0;\r
-#define LANGOPT(Name, Bits, Default, Description) \\r
- LangOpts.Name = Record[Idx++];\r
-#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \\r
- LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++]));\r
-#include "clang/Basic/LangOptions.def"\r
-\r
- ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++];\r
- VersionTuple runtimeVersion = ReadVersionTuple(Record, Idx);\r
- LangOpts.ObjCRuntime = ObjCRuntime(runtimeKind, runtimeVersion);\r
- \r
- unsigned Length = Record[Idx++];\r
- LangOpts.CurrentModule.assign(Record.begin() + Idx, \r
- Record.begin() + Idx + Length);\r
- return Listener.ReadLanguageOptions(LangOpts, Complain);\r
-}\r
-\r
-bool ASTReader::ParseTargetOptions(const RecordData &Record,\r
- bool Complain,\r
- ASTReaderListener &Listener) {\r
- unsigned Idx = 0;\r
- TargetOptions TargetOpts;\r
- TargetOpts.Triple = ReadString(Record, Idx);\r
- TargetOpts.CPU = ReadString(Record, Idx);\r
- TargetOpts.ABI = ReadString(Record, Idx);\r
- TargetOpts.CXXABI = ReadString(Record, Idx);\r
- TargetOpts.LinkerVersion = ReadString(Record, Idx);\r
- for (unsigned N = Record[Idx++]; N; --N) {\r
- TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx));\r
- }\r
- for (unsigned N = Record[Idx++]; N; --N) {\r
- TargetOpts.Features.push_back(ReadString(Record, Idx));\r
- }\r
-\r
- return Listener.ReadTargetOptions(TargetOpts, Complain);\r
-}\r
-\r
-bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain,\r
- ASTReaderListener &Listener) {\r
- DiagnosticOptions DiagOpts;\r
- unsigned Idx = 0;\r
-#define DIAGOPT(Name, Bits, Default) DiagOpts.Name = Record[Idx++];\r
-#define ENUM_DIAGOPT(Name, Type, Bits, Default) \\r
- DiagOpts.set##Name(static_cast<Type>(Record[Idx++]));\r
-#include "clang/Basic/DiagnosticOptions.def"\r
-\r
- for (unsigned N = Record[Idx++]; N; --N) {\r
- DiagOpts.Warnings.push_back(ReadString(Record, Idx));\r
- }\r
-\r
- return Listener.ReadDiagnosticOptions(DiagOpts, Complain);\r
-}\r
-\r
-bool ASTReader::ParseFileSystemOptions(const RecordData &Record, bool Complain,\r
- ASTReaderListener &Listener) {\r
- FileSystemOptions FSOpts;\r
- unsigned Idx = 0;\r
- FSOpts.WorkingDir = ReadString(Record, Idx);\r
- return Listener.ReadFileSystemOptions(FSOpts, Complain);\r
-}\r
-\r
-bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,\r
- bool Complain,\r
- ASTReaderListener &Listener) {\r
- HeaderSearchOptions HSOpts;\r
- unsigned Idx = 0;\r
- HSOpts.Sysroot = ReadString(Record, Idx);\r
-\r
- // Include entries.\r
- for (unsigned N = Record[Idx++]; N; --N) {\r
- std::string Path = ReadString(Record, Idx);\r
- frontend::IncludeDirGroup Group\r
- = static_cast<frontend::IncludeDirGroup>(Record[Idx++]);\r
- bool IsUserSupplied = Record[Idx++];\r
- bool IsFramework = Record[Idx++];\r
- bool IgnoreSysRoot = Record[Idx++];\r
- bool IsInternal = Record[Idx++];\r
- bool ImplicitExternC = Record[Idx++];\r
- HSOpts.UserEntries.push_back(\r
- HeaderSearchOptions::Entry(Path, Group, IsUserSupplied, IsFramework,\r
- IgnoreSysRoot, IsInternal, ImplicitExternC));\r
- }\r
-\r
- // System header prefixes.\r
- for (unsigned N = Record[Idx++]; N; --N) {\r
- std::string Prefix = ReadString(Record, Idx);\r
- bool IsSystemHeader = Record[Idx++];\r
- HSOpts.SystemHeaderPrefixes.push_back(\r
- HeaderSearchOptions::SystemHeaderPrefix(Prefix, IsSystemHeader));\r
- }\r
-\r
- HSOpts.ResourceDir = ReadString(Record, Idx);\r
- HSOpts.ModuleCachePath = ReadString(Record, Idx);\r
- HSOpts.DisableModuleHash = Record[Idx++];\r
- HSOpts.UseBuiltinIncludes = Record[Idx++];\r
- HSOpts.UseStandardSystemIncludes = Record[Idx++];\r
- HSOpts.UseStandardCXXIncludes = Record[Idx++];\r
- HSOpts.UseLibcxx = Record[Idx++];\r
-\r
- return Listener.ReadHeaderSearchOptions(HSOpts, Complain);\r
-}\r
-\r
-bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,\r
- bool Complain,\r
- ASTReaderListener &Listener,\r
- std::string &SuggestedPredefines) {\r
- PreprocessorOptions PPOpts;\r
- unsigned Idx = 0;\r
-\r
- // Macro definitions/undefs\r
- for (unsigned N = Record[Idx++]; N; --N) {\r
- std::string Macro = ReadString(Record, Idx);\r
- bool IsUndef = Record[Idx++];\r
- PPOpts.Macros.push_back(std::make_pair(Macro, IsUndef));\r
- }\r
-\r
- // Includes\r
- for (unsigned N = Record[Idx++]; N; --N) {\r
- PPOpts.Includes.push_back(ReadString(Record, Idx));\r
- }\r
-\r
- // Macro Includes\r
- for (unsigned N = Record[Idx++]; N; --N) {\r
- PPOpts.MacroIncludes.push_back(ReadString(Record, Idx));\r
- }\r
-\r
- PPOpts.UsePredefines = Record[Idx++];\r
- PPOpts.ImplicitPCHInclude = ReadString(Record, Idx);\r
- PPOpts.ImplicitPTHInclude = ReadString(Record, Idx);\r
- PPOpts.ObjCXXARCStandardLibrary =\r
- static_cast<ObjCXXARCStandardLibraryKind>(Record[Idx++]);\r
- SuggestedPredefines.clear();\r
- return Listener.ReadPreprocessorOptions(PPOpts, Complain,\r
- SuggestedPredefines);\r
-}\r
-\r
-std::pair<ModuleFile *, unsigned>\r
-ASTReader::getModulePreprocessedEntity(unsigned GlobalIndex) {\r
- GlobalPreprocessedEntityMapType::iterator\r
- I = GlobalPreprocessedEntityMap.find(GlobalIndex);\r
- assert(I != GlobalPreprocessedEntityMap.end() && \r
- "Corrupted global preprocessed entity map");\r
- ModuleFile *M = I->second;\r
- unsigned LocalIndex = GlobalIndex - M->BasePreprocessedEntityID;\r
- return std::make_pair(M, LocalIndex);\r
-}\r
-\r
-std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>\r
-ASTReader::getModulePreprocessedEntities(ModuleFile &Mod) const {\r
- if (PreprocessingRecord *PPRec = PP.getPreprocessingRecord())\r
- return PPRec->getIteratorsForLoadedRange(Mod.BasePreprocessedEntityID,\r
- Mod.NumPreprocessedEntities);\r
-\r
- return std::make_pair(PreprocessingRecord::iterator(),\r
- PreprocessingRecord::iterator());\r
-}\r
-\r
-std::pair<ASTReader::ModuleDeclIterator, ASTReader::ModuleDeclIterator>\r
-ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) {\r
- return std::make_pair(ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls),\r
- ModuleDeclIterator(this, &Mod,\r
- Mod.FileSortedDecls + Mod.NumFileSortedDecls));\r
-}\r
-\r
-PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {\r
- PreprocessedEntityID PPID = Index+1;\r
- std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index);\r
- ModuleFile &M = *PPInfo.first;\r
- unsigned LocalIndex = PPInfo.second;\r
- const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex];\r
-\r
- SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor); \r
- M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset);\r
-\r
- unsigned Code = M.PreprocessorDetailCursor.ReadCode();\r
- switch (Code) {\r
- case llvm::bitc::END_BLOCK:\r
- return 0;\r
- \r
- case llvm::bitc::ENTER_SUBBLOCK:\r
- Error("unexpected subblock record in preprocessor detail block");\r
- return 0;\r
- \r
- case llvm::bitc::DEFINE_ABBREV:\r
- Error("unexpected abbrevation record in preprocessor detail block");\r
- return 0;\r
- \r
- default:\r
- break;\r
- }\r
-\r
- if (!PP.getPreprocessingRecord()) {\r
- Error("no preprocessing record");\r
- return 0;\r
- }\r
- \r
- // Read the record.\r
- SourceRange Range(ReadSourceLocation(M, PPOffs.Begin),\r
- ReadSourceLocation(M, PPOffs.End));\r
- PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();\r
- const char *BlobStart = 0;\r
- unsigned BlobLen = 0;\r
- RecordData Record;\r
- PreprocessorDetailRecordTypes RecType =\r
- (PreprocessorDetailRecordTypes)M.PreprocessorDetailCursor.ReadRecord(\r
- Code, Record, BlobStart, BlobLen);\r
- switch (RecType) {\r
- case PPD_MACRO_EXPANSION: {\r
- bool isBuiltin = Record[0];\r
- IdentifierInfo *Name = 0;\r
- MacroDefinition *Def = 0;\r
- if (isBuiltin)\r
- Name = getLocalIdentifier(M, Record[1]);\r
- else {\r
- PreprocessedEntityID\r
- GlobalID = getGlobalPreprocessedEntityID(M, Record[1]);\r
- Def =cast<MacroDefinition>(PPRec.getLoadedPreprocessedEntity(GlobalID-1));\r
- }\r
-\r
- MacroExpansion *ME;\r
- if (isBuiltin)\r
- ME = new (PPRec) MacroExpansion(Name, Range);\r
- else\r
- ME = new (PPRec) MacroExpansion(Def, Range);\r
-\r
- return ME;\r
- }\r
- \r
- case PPD_MACRO_DEFINITION: {\r
- // Decode the identifier info and then check again; if the macro is\r
- // still defined and associated with the identifier,\r
- IdentifierInfo *II = getLocalIdentifier(M, Record[0]);\r
- MacroDefinition *MD\r
- = new (PPRec) MacroDefinition(II, Range);\r
-\r
- if (DeserializationListener)\r
- DeserializationListener->MacroDefinitionRead(PPID, MD);\r
-\r
- return MD;\r
- }\r
- \r
- case PPD_INCLUSION_DIRECTIVE: {\r
- const char *FullFileNameStart = BlobStart + Record[0];\r
- StringRef FullFileName(FullFileNameStart, BlobLen - Record[0]);\r
- const FileEntry *File = 0;\r
- if (!FullFileName.empty())\r
- File = PP.getFileManager().getFile(FullFileName);\r
- \r
- // FIXME: Stable encoding\r
- InclusionDirective::InclusionKind Kind\r
- = static_cast<InclusionDirective::InclusionKind>(Record[2]);\r
- InclusionDirective *ID\r
- = new (PPRec) InclusionDirective(PPRec, Kind,\r
- StringRef(BlobStart, Record[0]),\r
- Record[1], Record[3],\r
- File,\r
- Range);\r
- return ID;\r
- }\r
- }\r
-\r
- llvm_unreachable("Invalid PreprocessorDetailRecordTypes");\r
-}\r
-\r
-/// \brief \arg SLocMapI points at a chunk of a module that contains no\r
-/// preprocessed entities or the entities it contains are not the ones we are\r
-/// looking for. Find the next module that contains entities and return the ID\r
-/// of the first entry.\r
-PreprocessedEntityID ASTReader::findNextPreprocessedEntity(\r
- GlobalSLocOffsetMapType::const_iterator SLocMapI) const {\r
- ++SLocMapI;\r
- for (GlobalSLocOffsetMapType::const_iterator\r
- EndI = GlobalSLocOffsetMap.end(); SLocMapI != EndI; ++SLocMapI) {\r
- ModuleFile &M = *SLocMapI->second;\r
- if (M.NumPreprocessedEntities)\r
- return M.BasePreprocessedEntityID;\r
- }\r
-\r
- return getTotalNumPreprocessedEntities();\r
-}\r
-\r
-namespace {\r
-\r
-template <unsigned PPEntityOffset::*PPLoc>\r
-struct PPEntityComp {\r
- const ASTReader &Reader;\r
- ModuleFile &M;\r
-\r
- PPEntityComp(const ASTReader &Reader, ModuleFile &M) : Reader(Reader), M(M) { }\r
-\r
- bool operator()(const PPEntityOffset &L, const PPEntityOffset &R) const {\r
- SourceLocation LHS = getLoc(L);\r
- SourceLocation RHS = getLoc(R);\r
- return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);\r
- }\r
-\r
- bool operator()(const PPEntityOffset &L, SourceLocation RHS) const {\r
- SourceLocation LHS = getLoc(L);\r
- return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);\r
- }\r
-\r
- bool operator()(SourceLocation LHS, const PPEntityOffset &R) const {\r
- SourceLocation RHS = getLoc(R);\r
- return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);\r
- }\r
-\r
- SourceLocation getLoc(const PPEntityOffset &PPE) const {\r
- return Reader.ReadSourceLocation(M, PPE.*PPLoc);\r
- }\r
-};\r
-\r
-}\r
-\r
-/// \brief Returns the first preprocessed entity ID that ends after \arg BLoc.\r
-PreprocessedEntityID\r
-ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const {\r
- if (SourceMgr.isLocalSourceLocation(BLoc))\r
- return getTotalNumPreprocessedEntities();\r
-\r
- GlobalSLocOffsetMapType::const_iterator\r
- SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -\r
- BLoc.getOffset());\r
- assert(SLocMapI != GlobalSLocOffsetMap.end() &&\r
- "Corrupted global sloc offset map");\r
-\r
- if (SLocMapI->second->NumPreprocessedEntities == 0)\r
- return findNextPreprocessedEntity(SLocMapI);\r
-\r
- ModuleFile &M = *SLocMapI->second;\r
- typedef const PPEntityOffset *pp_iterator;\r
- pp_iterator pp_begin = M.PreprocessedEntityOffsets;\r
- pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities;\r
-\r
- size_t Count = M.NumPreprocessedEntities;\r
- size_t Half;\r
- pp_iterator First = pp_begin;\r
- pp_iterator PPI;\r
-\r
- // Do a binary search manually instead of using std::lower_bound because\r
- // The end locations of entities may be unordered (when a macro expansion\r
- // is inside another macro argument), but for this case it is not important\r
- // whether we get the first macro expansion or its containing macro.\r
- while (Count > 0) {\r
- Half = Count/2;\r
- PPI = First;\r
- std::advance(PPI, Half);\r
- if (SourceMgr.isBeforeInTranslationUnit(ReadSourceLocation(M, PPI->End),\r
- BLoc)){\r
- First = PPI;\r
- ++First;\r
- Count = Count - Half - 1;\r
- } else\r
- Count = Half;\r
- }\r
-\r
- if (PPI == pp_end)\r
- return findNextPreprocessedEntity(SLocMapI);\r
-\r
- return M.BasePreprocessedEntityID + (PPI - pp_begin);\r
-}\r
-\r
-/// \brief Returns the first preprocessed entity ID that begins after \arg ELoc.\r
-PreprocessedEntityID\r
-ASTReader::findEndPreprocessedEntity(SourceLocation ELoc) const {\r
- if (SourceMgr.isLocalSourceLocation(ELoc))\r
- return getTotalNumPreprocessedEntities();\r
-\r
- GlobalSLocOffsetMapType::const_iterator\r
- SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -\r
- ELoc.getOffset());\r
- assert(SLocMapI != GlobalSLocOffsetMap.end() &&\r
- "Corrupted global sloc offset map");\r
-\r
- if (SLocMapI->second->NumPreprocessedEntities == 0)\r
- return findNextPreprocessedEntity(SLocMapI);\r
-\r
- ModuleFile &M = *SLocMapI->second;\r
- typedef const PPEntityOffset *pp_iterator;\r
- pp_iterator pp_begin = M.PreprocessedEntityOffsets;\r
- pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities;\r
- pp_iterator PPI =\r
- std::upper_bound(pp_begin, pp_end, ELoc,\r
- PPEntityComp<&PPEntityOffset::Begin>(*this, M));\r
-\r
- if (PPI == pp_end)\r
- return findNextPreprocessedEntity(SLocMapI);\r
-\r
- return M.BasePreprocessedEntityID + (PPI - pp_begin);\r
-}\r
-\r
-/// \brief Returns a pair of [Begin, End) indices of preallocated\r
-/// preprocessed entities that \arg Range encompasses.\r
-std::pair<unsigned, unsigned>\r
- ASTReader::findPreprocessedEntitiesInRange(SourceRange Range) {\r
- if (Range.isInvalid())\r
- return std::make_pair(0,0);\r
- assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));\r
-\r
- PreprocessedEntityID BeginID = findBeginPreprocessedEntity(Range.getBegin());\r
- PreprocessedEntityID EndID = findEndPreprocessedEntity(Range.getEnd());\r
- return std::make_pair(BeginID, EndID);\r
-}\r
-\r
-/// \brief Optionally returns true or false if the preallocated preprocessed\r
-/// entity with index \arg Index came from file \arg FID.\r
-llvm::Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index,\r
- FileID FID) {\r
- if (FID.isInvalid())\r
- return false;\r
-\r
- std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index);\r
- ModuleFile &M = *PPInfo.first;\r
- unsigned LocalIndex = PPInfo.second;\r
- const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex];\r
- \r
- SourceLocation Loc = ReadSourceLocation(M, PPOffs.Begin);\r
- if (Loc.isInvalid())\r
- return false;\r
- \r
- if (SourceMgr.isInFileID(SourceMgr.getFileLoc(Loc), FID))\r
- return true;\r
- else\r
- return false;\r
-}\r
-\r
-namespace {\r
- /// \brief Visitor used to search for information about a header file.\r
- class HeaderFileInfoVisitor {\r
- ASTReader &Reader;\r
- const FileEntry *FE;\r
- \r
- llvm::Optional<HeaderFileInfo> HFI;\r
- \r
- public:\r
- HeaderFileInfoVisitor(ASTReader &Reader, const FileEntry *FE)\r
- : Reader(Reader), FE(FE) { }\r
- \r
- static bool visit(ModuleFile &M, void *UserData) {\r
- HeaderFileInfoVisitor *This\r
- = static_cast<HeaderFileInfoVisitor *>(UserData);\r
- \r
- HeaderFileInfoTrait Trait(This->Reader, M, \r
- &This->Reader.getPreprocessor().getHeaderSearchInfo(),\r
- M.HeaderFileFrameworkStrings,\r
- This->FE->getName());\r
- \r
- HeaderFileInfoLookupTable *Table\r
- = static_cast<HeaderFileInfoLookupTable *>(M.HeaderFileInfoTable);\r
- if (!Table)\r
- return false;\r
-\r
- // Look in the on-disk hash table for an entry for this file name.\r
- HeaderFileInfoLookupTable::iterator Pos = Table->find(This->FE->getName(),\r
- &Trait);\r
- if (Pos == Table->end())\r
- return false;\r
-\r
- This->HFI = *Pos;\r
- return true;\r
- }\r
- \r
- llvm::Optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; }\r
- };\r
-}\r
-\r
-HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) {\r
- HeaderFileInfoVisitor Visitor(*this, FE);\r
- ModuleMgr.visit(&HeaderFileInfoVisitor::visit, &Visitor);\r
- if (llvm::Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo()) {\r
- if (Listener)\r
- Listener->ReadHeaderFileInfo(*HFI, FE->getUID());\r
- return *HFI;\r
- }\r
- \r
- return HeaderFileInfo();\r
-}\r
-\r
-void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {\r
- // FIXME: Make it work properly with modules.\r
- llvm::SmallVector<DiagnosticsEngine::DiagState *, 32> DiagStates;\r
- for (ModuleIterator I = ModuleMgr.begin(), E = ModuleMgr.end(); I != E; ++I) {\r
- ModuleFile &F = *(*I);\r
- unsigned Idx = 0;\r
- DiagStates.clear();\r
- assert(!Diag.DiagStates.empty());\r
- DiagStates.push_back(&Diag.DiagStates.front()); // the command-line one.\r
- while (Idx < F.PragmaDiagMappings.size()) {\r
- SourceLocation Loc = ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]);\r
- unsigned DiagStateID = F.PragmaDiagMappings[Idx++];\r
- if (DiagStateID != 0) {\r
- Diag.DiagStatePoints.push_back(\r
- DiagnosticsEngine::DiagStatePoint(DiagStates[DiagStateID-1],\r
- FullSourceLoc(Loc, SourceMgr)));\r
- continue;\r
- }\r
- \r
- assert(DiagStateID == 0);\r
- // A new DiagState was created here.\r
- Diag.DiagStates.push_back(*Diag.GetCurDiagState());\r
- DiagnosticsEngine::DiagState *NewState = &Diag.DiagStates.back();\r
- DiagStates.push_back(NewState);\r
- Diag.DiagStatePoints.push_back(\r
- DiagnosticsEngine::DiagStatePoint(NewState,\r
- FullSourceLoc(Loc, SourceMgr)));\r
- while (1) {\r
- assert(Idx < F.PragmaDiagMappings.size() &&\r
- "Invalid data, didn't find '-1' marking end of diag/map pairs");\r
- if (Idx >= F.PragmaDiagMappings.size()) {\r
- break; // Something is messed up but at least avoid infinite loop in\r
- // release build.\r
- }\r
- unsigned DiagID = F.PragmaDiagMappings[Idx++];\r
- if (DiagID == (unsigned)-1) {\r
- break; // no more diag/map pairs for this location.\r
- }\r
- diag::Mapping Map = (diag::Mapping)F.PragmaDiagMappings[Idx++];\r
- DiagnosticMappingInfo MappingInfo = Diag.makeMappingInfo(Map, Loc);\r
- Diag.GetCurDiagState()->setMappingInfo(DiagID, MappingInfo);\r
- }\r
- }\r
- }\r
-}\r
-\r
-/// \brief Get the correct cursor and offset for loading a type.\r
-ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) {\r
- GlobalTypeMapType::iterator I = GlobalTypeMap.find(Index);\r
- assert(I != GlobalTypeMap.end() && "Corrupted global type map");\r
- ModuleFile *M = I->second;\r
- return RecordLocation(M, M->TypeOffsets[Index - M->BaseTypeIndex]);\r
-}\r
-\r
-/// \brief Read and return the type with the given index..\r
-///\r
-/// The index is the type ID, shifted and minus the number of predefs. This\r
-/// routine actually reads the record corresponding to the type at the given\r
-/// location. It is a helper routine for GetType, which deals with reading type\r
-/// IDs.\r
-QualType ASTReader::readTypeRecord(unsigned Index) {\r
- RecordLocation Loc = TypeCursorForIndex(Index);\r
- llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor;\r
-\r
- // Keep track of where we are in the stream, then jump back there\r
- // after reading this type.\r
- SavedStreamPosition SavedPosition(DeclsCursor);\r
-\r
- ReadingKindTracker ReadingKind(Read_Type, *this);\r
-\r
- // Note that we are loading a type record.\r
- Deserializing AType(this);\r
-\r
- unsigned Idx = 0;\r
- DeclsCursor.JumpToBit(Loc.Offset);\r
- RecordData Record;\r
- unsigned Code = DeclsCursor.ReadCode();\r
- switch ((TypeCode)DeclsCursor.ReadRecord(Code, Record)) {\r
- case TYPE_EXT_QUAL: {\r
- if (Record.size() != 2) {\r
- Error("Incorrect encoding of extended qualifier type");\r
- return QualType();\r
- }\r
- QualType Base = readType(*Loc.F, Record, Idx);\r
- Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[Idx++]);\r
- return Context.getQualifiedType(Base, Quals);\r
- }\r
-\r
- case TYPE_COMPLEX: {\r
- if (Record.size() != 1) {\r
- Error("Incorrect encoding of complex type");\r
- return QualType();\r
- }\r
- QualType ElemType = readType(*Loc.F, Record, Idx);\r
- return Context.getComplexType(ElemType);\r
- }\r
-\r
- case TYPE_POINTER: {\r
- if (Record.size() != 1) {\r
- Error("Incorrect encoding of pointer type");\r
- return QualType();\r
- }\r
- QualType PointeeType = readType(*Loc.F, Record, Idx);\r
- return Context.getPointerType(PointeeType);\r
- }\r
-\r
- case TYPE_BLOCK_POINTER: {\r
- if (Record.size() != 1) {\r
- Error("Incorrect encoding of block pointer type");\r
- return QualType();\r
- }\r
- QualType PointeeType = readType(*Loc.F, Record, Idx);\r
- return Context.getBlockPointerType(PointeeType);\r
- }\r
-\r
- case TYPE_LVALUE_REFERENCE: {\r
- if (Record.size() != 2) {\r
- Error("Incorrect encoding of lvalue reference type");\r
- return QualType();\r
- }\r
- QualType PointeeType = readType(*Loc.F, Record, Idx);\r
- return Context.getLValueReferenceType(PointeeType, Record[1]);\r
- }\r
-\r
- case TYPE_RVALUE_REFERENCE: {\r
- if (Record.size() != 1) {\r
- Error("Incorrect encoding of rvalue reference type");\r
- return QualType();\r
- }\r
- QualType PointeeType = readType(*Loc.F, Record, Idx);\r
- return Context.getRValueReferenceType(PointeeType);\r
- }\r
-\r
- case TYPE_MEMBER_POINTER: {\r
- if (Record.size() != 2) {\r
- Error("Incorrect encoding of member pointer type");\r
- return QualType();\r
- }\r
- QualType PointeeType = readType(*Loc.F, Record, Idx);\r
- QualType ClassType = readType(*Loc.F, Record, Idx);\r
- if (PointeeType.isNull() || ClassType.isNull())\r
- return QualType();\r
- \r
- return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());\r
- }\r
-\r
- case TYPE_CONSTANT_ARRAY: {\r
- QualType ElementType = readType(*Loc.F, Record, Idx);\r
- ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];\r
- unsigned IndexTypeQuals = Record[2];\r
- unsigned Idx = 3;\r
- llvm::APInt Size = ReadAPInt(Record, Idx);\r
- return Context.getConstantArrayType(ElementType, Size,\r
- ASM, IndexTypeQuals);\r
- }\r
-\r
- case TYPE_INCOMPLETE_ARRAY: {\r
- QualType ElementType = readType(*Loc.F, Record, Idx);\r
- ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];\r
- unsigned IndexTypeQuals = Record[2];\r
- return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);\r
- }\r
-\r
- case TYPE_VARIABLE_ARRAY: {\r
- QualType ElementType = readType(*Loc.F, Record, Idx);\r
- ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];\r
- unsigned IndexTypeQuals = Record[2];\r
- SourceLocation LBLoc = ReadSourceLocation(*Loc.F, Record[3]);\r
- SourceLocation RBLoc = ReadSourceLocation(*Loc.F, Record[4]);\r
- return Context.getVariableArrayType(ElementType, ReadExpr(*Loc.F),\r
- ASM, IndexTypeQuals,\r
- SourceRange(LBLoc, RBLoc));\r
- }\r
-\r
- case TYPE_VECTOR: {\r
- if (Record.size() != 3) {\r
- Error("incorrect encoding of vector type in AST file");\r
- return QualType();\r
- }\r
-\r
- QualType ElementType = readType(*Loc.F, Record, Idx);\r
- unsigned NumElements = Record[1];\r
- unsigned VecKind = Record[2];\r
- return Context.getVectorType(ElementType, NumElements,\r
- (VectorType::VectorKind)VecKind);\r
- }\r
-\r
- case TYPE_EXT_VECTOR: {\r
- if (Record.size() != 3) {\r
- Error("incorrect encoding of extended vector type in AST file");\r
- return QualType();\r
- }\r
-\r
- QualType ElementType = readType(*Loc.F, Record, Idx);\r
- unsigned NumElements = Record[1];\r
- return Context.getExtVectorType(ElementType, NumElements);\r
- }\r
-\r
- case TYPE_FUNCTION_NO_PROTO: {\r
- if (Record.size() != 6) {\r
- Error("incorrect encoding of no-proto function type");\r
- return QualType();\r
- }\r
- QualType ResultType = readType(*Loc.F, Record, Idx);\r
- FunctionType::ExtInfo Info(Record[1], Record[2], Record[3],\r
- (CallingConv)Record[4], Record[5]);\r
- return Context.getFunctionNoProtoType(ResultType, Info);\r
- }\r
-\r
- case TYPE_FUNCTION_PROTO: {\r
- QualType ResultType = readType(*Loc.F, Record, Idx);\r
-\r
- FunctionProtoType::ExtProtoInfo EPI;\r
- EPI.ExtInfo = FunctionType::ExtInfo(/*noreturn*/ Record[1],\r
- /*hasregparm*/ Record[2],\r
- /*regparm*/ Record[3],\r
- static_cast<CallingConv>(Record[4]),\r
- /*produces*/ Record[5]);\r
-\r
- unsigned Idx = 6;\r
- unsigned NumParams = Record[Idx++];\r
- SmallVector<QualType, 16> ParamTypes;\r
- for (unsigned I = 0; I != NumParams; ++I)\r
- ParamTypes.push_back(readType(*Loc.F, Record, Idx));\r
-\r
- EPI.Variadic = Record[Idx++];\r
- EPI.HasTrailingReturn = Record[Idx++];\r
- EPI.TypeQuals = Record[Idx++];\r
- EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]);\r
- ExceptionSpecificationType EST =\r
- static_cast<ExceptionSpecificationType>(Record[Idx++]);\r
- EPI.ExceptionSpecType = EST;\r
- SmallVector<QualType, 2> Exceptions;\r
- if (EST == EST_Dynamic) {\r
- EPI.NumExceptions = Record[Idx++];\r
- for (unsigned I = 0; I != EPI.NumExceptions; ++I)\r
- Exceptions.push_back(readType(*Loc.F, Record, Idx));\r
- EPI.Exceptions = Exceptions.data();\r
- } else if (EST == EST_ComputedNoexcept) {\r
- EPI.NoexceptExpr = ReadExpr(*Loc.F);\r
- } else if (EST == EST_Uninstantiated) {\r
- EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);\r
- EPI.ExceptionSpecTemplate = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);\r
- } else if (EST == EST_Unevaluated) {\r
- EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);\r
- }\r
- return Context.getFunctionType(ResultType, ParamTypes.data(), NumParams,\r
- EPI);\r
- }\r
-\r
- case TYPE_UNRESOLVED_USING: {\r
- unsigned Idx = 0;\r
- return Context.getTypeDeclType(\r
- ReadDeclAs<UnresolvedUsingTypenameDecl>(*Loc.F, Record, Idx));\r
- }\r
- \r
- case TYPE_TYPEDEF: {\r
- if (Record.size() != 2) {\r
- Error("incorrect encoding of typedef type");\r
- return QualType();\r
- }\r
- unsigned Idx = 0;\r
- TypedefNameDecl *Decl = ReadDeclAs<TypedefNameDecl>(*Loc.F, Record, Idx);\r
- QualType Canonical = readType(*Loc.F, Record, Idx);\r
- if (!Canonical.isNull())\r
- Canonical = Context.getCanonicalType(Canonical);\r
- return Context.getTypedefType(Decl, Canonical);\r
- }\r
-\r
- case TYPE_TYPEOF_EXPR:\r
- return Context.getTypeOfExprType(ReadExpr(*Loc.F));\r
-\r
- case TYPE_TYPEOF: {\r
- if (Record.size() != 1) {\r
- Error("incorrect encoding of typeof(type) in AST file");\r
- return QualType();\r
- }\r
- QualType UnderlyingType = readType(*Loc.F, Record, Idx);\r
- return Context.getTypeOfType(UnderlyingType);\r
- }\r
-\r
- case TYPE_DECLTYPE: {\r
- QualType UnderlyingType = readType(*Loc.F, Record, Idx);\r
- return Context.getDecltypeType(ReadExpr(*Loc.F), UnderlyingType);\r
- }\r
-\r
- case TYPE_UNARY_TRANSFORM: {\r
- QualType BaseType = readType(*Loc.F, Record, Idx);\r
- QualType UnderlyingType = readType(*Loc.F, Record, Idx);\r
- UnaryTransformType::UTTKind UKind = (UnaryTransformType::UTTKind)Record[2];\r
- return Context.getUnaryTransformType(BaseType, UnderlyingType, UKind);\r
- }\r
-\r
- case TYPE_AUTO:\r
- return Context.getAutoType(readType(*Loc.F, Record, Idx));\r
-\r
- case TYPE_RECORD: {\r
- if (Record.size() != 2) {\r
- Error("incorrect encoding of record type");\r
- return QualType();\r
- }\r
- unsigned Idx = 0;\r
- bool IsDependent = Record[Idx++];\r
- RecordDecl *RD = ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx);\r
- RD = cast_or_null<RecordDecl>(RD->getCanonicalDecl());\r
- QualType T = Context.getRecordType(RD);\r
- const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);\r
- return T;\r
- }\r
-\r
- case TYPE_ENUM: {\r
- if (Record.size() != 2) {\r
- Error("incorrect encoding of enum type");\r
- return QualType();\r
- }\r
- unsigned Idx = 0;\r
- bool IsDependent = Record[Idx++];\r
- QualType T\r
- = Context.getEnumType(ReadDeclAs<EnumDecl>(*Loc.F, Record, Idx));\r
- const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);\r
- return T;\r
- }\r
-\r
- case TYPE_ATTRIBUTED: {\r
- if (Record.size() != 3) {\r
- Error("incorrect encoding of attributed type");\r
- return QualType();\r
- }\r
- QualType modifiedType = readType(*Loc.F, Record, Idx);\r
- QualType equivalentType = readType(*Loc.F, Record, Idx);\r
- AttributedType::Kind kind = static_cast<AttributedType::Kind>(Record[2]);\r
- return Context.getAttributedType(kind, modifiedType, equivalentType);\r
- }\r
-\r
- case TYPE_PAREN: {\r
- if (Record.size() != 1) {\r
- Error("incorrect encoding of paren type");\r
- return QualType();\r
- }\r
- QualType InnerType = readType(*Loc.F, Record, Idx);\r
- return Context.getParenType(InnerType);\r
- }\r
-\r
- case TYPE_PACK_EXPANSION: {\r
- if (Record.size() != 2) {\r
- Error("incorrect encoding of pack expansion type");\r
- return QualType();\r
- }\r
- QualType Pattern = readType(*Loc.F, Record, Idx);\r
- if (Pattern.isNull())\r
- return QualType();\r
- llvm::Optional<unsigned> NumExpansions;\r
- if (Record[1])\r
- NumExpansions = Record[1] - 1;\r
- return Context.getPackExpansionType(Pattern, NumExpansions);\r
- }\r
-\r
- case TYPE_ELABORATED: {\r
- unsigned Idx = 0;\r
- ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];\r
- NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);\r
- QualType NamedType = readType(*Loc.F, Record, Idx);\r
- return Context.getElaboratedType(Keyword, NNS, NamedType);\r
- }\r
-\r
- case TYPE_OBJC_INTERFACE: {\r
- unsigned Idx = 0;\r
- ObjCInterfaceDecl *ItfD\r
- = ReadDeclAs<ObjCInterfaceDecl>(*Loc.F, Record, Idx);\r
- return Context.getObjCInterfaceType(ItfD->getCanonicalDecl());\r
- }\r
-\r
- case TYPE_OBJC_OBJECT: {\r
- unsigned Idx = 0;\r
- QualType Base = readType(*Loc.F, Record, Idx);\r
- unsigned NumProtos = Record[Idx++];\r
- SmallVector<ObjCProtocolDecl*, 4> Protos;\r
- for (unsigned I = 0; I != NumProtos; ++I)\r
- Protos.push_back(ReadDeclAs<ObjCProtocolDecl>(*Loc.F, Record, Idx));\r
- return Context.getObjCObjectType(Base, Protos.data(), NumProtos);\r
- }\r
-\r
- case TYPE_OBJC_OBJECT_POINTER: {\r
- unsigned Idx = 0;\r
- QualType Pointee = readType(*Loc.F, Record, Idx);\r
- return Context.getObjCObjectPointerType(Pointee);\r
- }\r
-\r
- case TYPE_SUBST_TEMPLATE_TYPE_PARM: {\r
- unsigned Idx = 0;\r
- QualType Parm = readType(*Loc.F, Record, Idx);\r
- QualType Replacement = readType(*Loc.F, Record, Idx);\r
- return\r
- Context.getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),\r
- Replacement);\r
- }\r
-\r
- case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: {\r
- unsigned Idx = 0;\r
- QualType Parm = readType(*Loc.F, Record, Idx);\r
- TemplateArgument ArgPack = ReadTemplateArgument(*Loc.F, Record, Idx);\r
- return Context.getSubstTemplateTypeParmPackType(\r
- cast<TemplateTypeParmType>(Parm),\r
- ArgPack);\r
- }\r
-\r
- case TYPE_INJECTED_CLASS_NAME: {\r
- CXXRecordDecl *D = ReadDeclAs<CXXRecordDecl>(*Loc.F, Record, Idx);\r
- QualType TST = readType(*Loc.F, Record, Idx); // probably derivable\r
- // FIXME: ASTContext::getInjectedClassNameType is not currently suitable\r
- // for AST reading, too much interdependencies.\r
- return\r
- QualType(new (Context, TypeAlignment) InjectedClassNameType(D, TST), 0);\r
- }\r
-\r
- case TYPE_TEMPLATE_TYPE_PARM: {\r
- unsigned Idx = 0;\r
- unsigned Depth = Record[Idx++];\r
- unsigned Index = Record[Idx++];\r
- bool Pack = Record[Idx++];\r
- TemplateTypeParmDecl *D\r
- = ReadDeclAs<TemplateTypeParmDecl>(*Loc.F, Record, Idx);\r
- return Context.getTemplateTypeParmType(Depth, Index, Pack, D);\r
- }\r
-\r
- case TYPE_DEPENDENT_NAME: {\r
- unsigned Idx = 0;\r
- ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];\r
- NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);\r
- const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx);\r
- QualType Canon = readType(*Loc.F, Record, Idx);\r
- if (!Canon.isNull())\r
- Canon = Context.getCanonicalType(Canon);\r
- return Context.getDependentNameType(Keyword, NNS, Name, Canon);\r
- }\r
-\r
- case TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: {\r
- unsigned Idx = 0;\r
- ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];\r
- NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);\r
- const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx);\r
- unsigned NumArgs = Record[Idx++];\r
- SmallVector<TemplateArgument, 8> Args;\r
- Args.reserve(NumArgs);\r
- while (NumArgs--)\r
- Args.push_back(ReadTemplateArgument(*Loc.F, Record, Idx));\r
- return Context.getDependentTemplateSpecializationType(Keyword, NNS, Name,\r
- Args.size(), Args.data());\r
- }\r
-\r
- case TYPE_DEPENDENT_SIZED_ARRAY: {\r
- unsigned Idx = 0;\r
-\r
- // ArrayType\r
- QualType ElementType = readType(*Loc.F, Record, Idx);\r
- ArrayType::ArraySizeModifier ASM\r
- = (ArrayType::ArraySizeModifier)Record[Idx++];\r
- unsigned IndexTypeQuals = Record[Idx++];\r
-\r
- // DependentSizedArrayType\r
- Expr *NumElts = ReadExpr(*Loc.F);\r
- SourceRange Brackets = ReadSourceRange(*Loc.F, Record, Idx);\r
-\r
- return Context.getDependentSizedArrayType(ElementType, NumElts, ASM,\r
- IndexTypeQuals, Brackets);\r
- }\r
-\r
- case TYPE_TEMPLATE_SPECIALIZATION: {\r
- unsigned Idx = 0;\r
- bool IsDependent = Record[Idx++];\r
- TemplateName Name = ReadTemplateName(*Loc.F, Record, Idx);\r
- SmallVector<TemplateArgument, 8> Args;\r
- ReadTemplateArgumentList(Args, *Loc.F, Record, Idx);\r
- QualType Underlying = readType(*Loc.F, Record, Idx);\r
- QualType T;\r
- if (Underlying.isNull())\r
- T = Context.getCanonicalTemplateSpecializationType(Name, Args.data(),\r
- Args.size());\r
- else\r
- T = Context.getTemplateSpecializationType(Name, Args.data(),\r
- Args.size(), Underlying);\r
- const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);\r
- return T;\r
- }\r
-\r
- case TYPE_ATOMIC: {\r
- if (Record.size() != 1) {\r
- Error("Incorrect encoding of atomic type");\r
- return QualType();\r
- }\r
- QualType ValueType = readType(*Loc.F, Record, Idx);\r
- return Context.getAtomicType(ValueType);\r
- }\r
- }\r
- llvm_unreachable("Invalid TypeCode!");\r
-}\r
-\r
-class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> {\r
- ASTReader &Reader;\r
- ModuleFile &F;\r
- const ASTReader::RecordData &Record;\r
- unsigned &Idx;\r
-\r
- SourceLocation ReadSourceLocation(const ASTReader::RecordData &R,\r
- unsigned &I) {\r
- return Reader.ReadSourceLocation(F, R, I);\r
- }\r
-\r
- template<typename T>\r
- T *ReadDeclAs(const ASTReader::RecordData &Record, unsigned &Idx) {\r
- return Reader.ReadDeclAs<T>(F, Record, Idx);\r
- }\r
- \r
-public:\r
- TypeLocReader(ASTReader &Reader, ModuleFile &F,\r
- const ASTReader::RecordData &Record, unsigned &Idx)\r
- : Reader(Reader), F(F), Record(Record), Idx(Idx)\r
- { }\r
-\r
- // We want compile-time assurance that we've enumerated all of\r
- // these, so unfortunately we have to declare them first, then\r
- // define them out-of-line.\r
-#define ABSTRACT_TYPELOC(CLASS, PARENT)\r
-#define TYPELOC(CLASS, PARENT) \\r
- void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);\r
-#include "clang/AST/TypeLocNodes.def"\r
-\r
- void VisitFunctionTypeLoc(FunctionTypeLoc);\r
- void VisitArrayTypeLoc(ArrayTypeLoc);\r
-};\r
-\r
-void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {\r
- // nothing to do\r
-}\r
-void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {\r
- TL.setBuiltinLoc(ReadSourceLocation(Record, Idx));\r
- if (TL.needsExtraLocalData()) {\r
- TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++]));\r
- TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++]));\r
- TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++]));\r
- TL.setModeAttr(Record[Idx++]);\r
- }\r
-}\r
-void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {\r
- TL.setStarLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {\r
- TL.setCaretLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {\r
- TL.setAmpLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {\r
- TL.setAmpAmpLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {\r
- TL.setStarLoc(ReadSourceLocation(Record, Idx));\r
- TL.setClassTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));\r
-}\r
-void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {\r
- TL.setLBracketLoc(ReadSourceLocation(Record, Idx));\r
- TL.setRBracketLoc(ReadSourceLocation(Record, Idx));\r
- if (Record[Idx++])\r
- TL.setSizeExpr(Reader.ReadExpr(F));\r
- else\r
- TL.setSizeExpr(0);\r
-}\r
-void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {\r
- VisitArrayTypeLoc(TL);\r
-}\r
-void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {\r
- VisitArrayTypeLoc(TL);\r
-}\r
-void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {\r
- VisitArrayTypeLoc(TL);\r
-}\r
-void TypeLocReader::VisitDependentSizedArrayTypeLoc(\r
- DependentSizedArrayTypeLoc TL) {\r
- VisitArrayTypeLoc(TL);\r
-}\r
-void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(\r
- DependentSizedExtVectorTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {\r
- TL.setLocalRangeBegin(ReadSourceLocation(Record, Idx));\r
- TL.setLParenLoc(ReadSourceLocation(Record, Idx));\r
- TL.setRParenLoc(ReadSourceLocation(Record, Idx));\r
- TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx));\r
- for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {\r
- TL.setArg(i, ReadDeclAs<ParmVarDecl>(Record, Idx));\r
- }\r
-}\r
-void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {\r
- VisitFunctionTypeLoc(TL);\r
-}\r
-void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {\r
- VisitFunctionTypeLoc(TL);\r
-}\r
-void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {\r
- TL.setTypeofLoc(ReadSourceLocation(Record, Idx));\r
- TL.setLParenLoc(ReadSourceLocation(Record, Idx));\r
- TL.setRParenLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {\r
- TL.setTypeofLoc(ReadSourceLocation(Record, Idx));\r
- TL.setLParenLoc(ReadSourceLocation(Record, Idx));\r
- TL.setRParenLoc(ReadSourceLocation(Record, Idx));\r
- TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));\r
-}\r
-void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {\r
- TL.setKWLoc(ReadSourceLocation(Record, Idx));\r
- TL.setLParenLoc(ReadSourceLocation(Record, Idx));\r
- TL.setRParenLoc(ReadSourceLocation(Record, Idx));\r
- TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));\r
-}\r
-void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {\r
- TL.setAttrNameLoc(ReadSourceLocation(Record, Idx));\r
- if (TL.hasAttrOperand()) {\r
- SourceRange range;\r
- range.setBegin(ReadSourceLocation(Record, Idx));\r
- range.setEnd(ReadSourceLocation(Record, Idx));\r
- TL.setAttrOperandParensRange(range);\r
- }\r
- if (TL.hasAttrExprOperand()) {\r
- if (Record[Idx++])\r
- TL.setAttrExprOperand(Reader.ReadExpr(F));\r
- else\r
- TL.setAttrExprOperand(0);\r
- } else if (TL.hasAttrEnumOperand())\r
- TL.setAttrEnumOperandLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(\r
- SubstTemplateTypeParmTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc(\r
- SubstTemplateTypeParmPackTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitTemplateSpecializationTypeLoc(\r
- TemplateSpecializationTypeLoc TL) {\r
- TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx));\r
- TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx));\r
- TL.setLAngleLoc(ReadSourceLocation(Record, Idx));\r
- TL.setRAngleLoc(ReadSourceLocation(Record, Idx));\r
- for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)\r
- TL.setArgLocInfo(i,\r
- Reader.GetTemplateArgumentLocInfo(F,\r
- TL.getTypePtr()->getArg(i).getKind(),\r
- Record, Idx));\r
-}\r
-void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) {\r
- TL.setLParenLoc(ReadSourceLocation(Record, Idx));\r
- TL.setRParenLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {\r
- TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));\r
- TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));\r
-}\r
-void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {\r
- TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));\r
- TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc(\r
- DependentTemplateSpecializationTypeLoc TL) {\r
- TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));\r
- TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));\r
- TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx));\r
- TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx));\r
- TL.setLAngleLoc(ReadSourceLocation(Record, Idx));\r
- TL.setRAngleLoc(ReadSourceLocation(Record, Idx));\r
- for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)\r
- TL.setArgLocInfo(I,\r
- Reader.GetTemplateArgumentLocInfo(F,\r
- TL.getTypePtr()->getArg(I).getKind(),\r
- Record, Idx));\r
-}\r
-void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {\r
- TL.setEllipsisLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {\r
- TL.setNameLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {\r
- TL.setHasBaseTypeAsWritten(Record[Idx++]);\r
- TL.setLAngleLoc(ReadSourceLocation(Record, Idx));\r
- TL.setRAngleLoc(ReadSourceLocation(Record, Idx));\r
- for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)\r
- TL.setProtocolLoc(i, ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {\r
- TL.setStarLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) {\r
- TL.setKWLoc(ReadSourceLocation(Record, Idx));\r
- TL.setLParenLoc(ReadSourceLocation(Record, Idx));\r
- TL.setRParenLoc(ReadSourceLocation(Record, Idx));\r
-}\r
-\r
-TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F,\r
- const RecordData &Record,\r
- unsigned &Idx) {\r
- QualType InfoTy = readType(F, Record, Idx);\r
- if (InfoTy.isNull())\r
- return 0;\r
-\r
- TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy);\r
- TypeLocReader TLR(*this, F, Record, Idx);\r
- for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())\r
- TLR.Visit(TL);\r
- return TInfo;\r
-}\r
-\r
-QualType ASTReader::GetType(TypeID ID) {\r
- unsigned FastQuals = ID & Qualifiers::FastMask;\r
- unsigned Index = ID >> Qualifiers::FastWidth;\r
-\r
- if (Index < NUM_PREDEF_TYPE_IDS) {\r
- QualType T;\r
- switch ((PredefinedTypeIDs)Index) {\r
- case PREDEF_TYPE_NULL_ID: return QualType();\r
- case PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;\r
- case PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;\r
-\r
- case PREDEF_TYPE_CHAR_U_ID:\r
- case PREDEF_TYPE_CHAR_S_ID:\r
- // FIXME: Check that the signedness of CharTy is correct!\r
- T = Context.CharTy;\r
- break;\r
-\r
- case PREDEF_TYPE_UCHAR_ID: T = Context.UnsignedCharTy; break;\r
- case PREDEF_TYPE_USHORT_ID: T = Context.UnsignedShortTy; break;\r
- case PREDEF_TYPE_UINT_ID: T = Context.UnsignedIntTy; break;\r
- case PREDEF_TYPE_ULONG_ID: T = Context.UnsignedLongTy; break;\r
- case PREDEF_TYPE_ULONGLONG_ID: T = Context.UnsignedLongLongTy; break;\r
- case PREDEF_TYPE_UINT128_ID: T = Context.UnsignedInt128Ty; break;\r
- case PREDEF_TYPE_SCHAR_ID: T = Context.SignedCharTy; break;\r
- case PREDEF_TYPE_WCHAR_ID: T = Context.WCharTy; break;\r
- case PREDEF_TYPE_SHORT_ID: T = Context.ShortTy; break;\r
- case PREDEF_TYPE_INT_ID: T = Context.IntTy; break;\r
- case PREDEF_TYPE_LONG_ID: T = Context.LongTy; break;\r
- case PREDEF_TYPE_LONGLONG_ID: T = Context.LongLongTy; break;\r
- case PREDEF_TYPE_INT128_ID: T = Context.Int128Ty; break;\r
- case PREDEF_TYPE_HALF_ID: T = Context.HalfTy; break;\r
- case PREDEF_TYPE_FLOAT_ID: T = Context.FloatTy; break;\r
- case PREDEF_TYPE_DOUBLE_ID: T = Context.DoubleTy; break;\r
- case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;\r
- case PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break;\r
- case PREDEF_TYPE_BOUND_MEMBER: T = Context.BoundMemberTy; break;\r
- case PREDEF_TYPE_PSEUDO_OBJECT: T = Context.PseudoObjectTy; break;\r
- case PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break;\r
- case PREDEF_TYPE_UNKNOWN_ANY: T = Context.UnknownAnyTy; break;\r
- case PREDEF_TYPE_NULLPTR_ID: T = Context.NullPtrTy; break;\r
- case PREDEF_TYPE_CHAR16_ID: T = Context.Char16Ty; break;\r
- case PREDEF_TYPE_CHAR32_ID: T = Context.Char32Ty; break;\r
- case PREDEF_TYPE_OBJC_ID: T = Context.ObjCBuiltinIdTy; break;\r
- case PREDEF_TYPE_OBJC_CLASS: T = Context.ObjCBuiltinClassTy; break;\r
- case PREDEF_TYPE_OBJC_SEL: T = Context.ObjCBuiltinSelTy; break;\r
- case PREDEF_TYPE_IMAGE1D_ID: T = Context.OCLImage1dTy; break;\r
- case PREDEF_TYPE_IMAGE1D_ARR_ID: T = Context.OCLImage1dArrayTy; break;\r
- case PREDEF_TYPE_IMAGE1D_BUFF_ID: T = Context.OCLImage1dBufferTy; break;\r
- case PREDEF_TYPE_IMAGE2D_ID: T = Context.OCLImage2dTy; break;\r
- case PREDEF_TYPE_IMAGE2D_ARR_ID: T = Context.OCLImage2dArrayTy; break;\r
- case PREDEF_TYPE_IMAGE3D_ID: T = Context.OCLImage3dTy; break;\r
- case PREDEF_TYPE_AUTO_DEDUCT: T = Context.getAutoDeductType(); break;\r
- \r
- case PREDEF_TYPE_AUTO_RREF_DEDUCT: \r
- T = Context.getAutoRRefDeductType(); \r
- break;\r
-\r
- case PREDEF_TYPE_ARC_UNBRIDGED_CAST:\r
- T = Context.ARCUnbridgedCastTy;\r
- break;\r
-\r
- case PREDEF_TYPE_VA_LIST_TAG:\r
- T = Context.getVaListTagType();\r
- break;\r
-\r
- case PREDEF_TYPE_BUILTIN_FN:\r
- T = Context.BuiltinFnTy;\r
- break;\r
- }\r
-\r
- assert(!T.isNull() && "Unknown predefined type");\r
- return T.withFastQualifiers(FastQuals);\r
- }\r
-\r
- Index -= NUM_PREDEF_TYPE_IDS;\r
- assert(Index < TypesLoaded.size() && "Type index out-of-range");\r
- if (TypesLoaded[Index].isNull()) {\r
- TypesLoaded[Index] = readTypeRecord(Index);\r
- if (TypesLoaded[Index].isNull())\r
- return QualType();\r
-\r
- TypesLoaded[Index]->setFromAST();\r
- if (DeserializationListener)\r
- DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID),\r
- TypesLoaded[Index]);\r
- }\r
-\r
- return TypesLoaded[Index].withFastQualifiers(FastQuals);\r
-}\r
-\r
-QualType ASTReader::getLocalType(ModuleFile &F, unsigned LocalID) {\r
- return GetType(getGlobalTypeID(F, LocalID));\r
-}\r
-\r
-serialization::TypeID \r
-ASTReader::getGlobalTypeID(ModuleFile &F, unsigned LocalID) const {\r
- unsigned FastQuals = LocalID & Qualifiers::FastMask;\r
- unsigned LocalIndex = LocalID >> Qualifiers::FastWidth;\r
- \r
- if (LocalIndex < NUM_PREDEF_TYPE_IDS)\r
- return LocalID;\r
-\r
- ContinuousRangeMap<uint32_t, int, 2>::iterator I\r
- = F.TypeRemap.find(LocalIndex - NUM_PREDEF_TYPE_IDS);\r
- assert(I != F.TypeRemap.end() && "Invalid index into type index remap");\r
- \r
- unsigned GlobalIndex = LocalIndex + I->second;\r
- return (GlobalIndex << Qualifiers::FastWidth) | FastQuals;\r
-}\r
-\r
-TemplateArgumentLocInfo\r
-ASTReader::GetTemplateArgumentLocInfo(ModuleFile &F,\r
- TemplateArgument::ArgKind Kind,\r
- const RecordData &Record,\r
- unsigned &Index) {\r
- switch (Kind) {\r
- case TemplateArgument::Expression:\r
- return ReadExpr(F);\r
- case TemplateArgument::Type:\r
- return GetTypeSourceInfo(F, Record, Index);\r
- case TemplateArgument::Template: {\r
- NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, \r
- Index);\r
- SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);\r
- return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc,\r
- SourceLocation());\r
- }\r
- case TemplateArgument::TemplateExpansion: {\r
- NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, \r
- Index);\r
- SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);\r
- SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index);\r
- return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc, \r
- EllipsisLoc);\r
- }\r
- case TemplateArgument::Null:\r
- case TemplateArgument::Integral:\r
- case TemplateArgument::Declaration:\r
- case TemplateArgument::NullPtr:\r
- case TemplateArgument::Pack:\r
- // FIXME: Is this right?\r
- return TemplateArgumentLocInfo();\r
- }\r
- llvm_unreachable("unexpected template argument loc");\r
-}\r
-\r
-TemplateArgumentLoc\r
-ASTReader::ReadTemplateArgumentLoc(ModuleFile &F,\r
- const RecordData &Record, unsigned &Index) {\r
- TemplateArgument Arg = ReadTemplateArgument(F, Record, Index);\r
-\r
- if (Arg.getKind() == TemplateArgument::Expression) {\r
- if (Record[Index++]) // bool InfoHasSameExpr.\r
- return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr()));\r
- }\r
- return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(F, Arg.getKind(),\r
- Record, Index));\r
-}\r
-\r
-Decl *ASTReader::GetExternalDecl(uint32_t ID) {\r
- return GetDecl(ID);\r
-}\r
-\r
-uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record, \r
- unsigned &Idx){\r
- if (Idx >= Record.size())\r
- return 0;\r
- \r
- unsigned LocalID = Record[Idx++];\r
- return getGlobalBitOffset(M, M.CXXBaseSpecifiersOffsets[LocalID - 1]);\r
-}\r
-\r
-CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) {\r
- RecordLocation Loc = getLocalBitOffset(Offset);\r
- llvm::BitstreamCursor &Cursor = Loc.F->DeclsCursor;\r
- SavedStreamPosition SavedPosition(Cursor);\r
- Cursor.JumpToBit(Loc.Offset);\r
- ReadingKindTracker ReadingKind(Read_Decl, *this);\r
- RecordData Record;\r
- unsigned Code = Cursor.ReadCode();\r
- unsigned RecCode = Cursor.ReadRecord(Code, Record);\r
- if (RecCode != DECL_CXX_BASE_SPECIFIERS) {\r
- Error("Malformed AST file: missing C++ base specifiers");\r
- return 0;\r
- }\r
-\r
- unsigned Idx = 0;\r
- unsigned NumBases = Record[Idx++];\r
- void *Mem = Context.Allocate(sizeof(CXXBaseSpecifier) * NumBases);\r
- CXXBaseSpecifier *Bases = new (Mem) CXXBaseSpecifier [NumBases];\r
- for (unsigned I = 0; I != NumBases; ++I)\r
- Bases[I] = ReadCXXBaseSpecifier(*Loc.F, Record, Idx);\r
- return Bases;\r
-}\r
-\r
-serialization::DeclID \r
-ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const {\r
- if (LocalID < NUM_PREDEF_DECL_IDS)\r
- return LocalID;\r
-\r
- ContinuousRangeMap<uint32_t, int, 2>::iterator I\r
- = F.DeclRemap.find(LocalID - NUM_PREDEF_DECL_IDS);\r
- assert(I != F.DeclRemap.end() && "Invalid index into decl index remap");\r
- \r
- return LocalID + I->second;\r
-}\r
-\r
-bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID,\r
- ModuleFile &M) const {\r
- GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(ID);\r
- assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");\r
- return &M == I->second;\r
-}\r
-\r
-ModuleFile *ASTReader::getOwningModuleFile(Decl *D) {\r
- if (!D->isFromASTFile())\r
- return 0;\r
- GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID());\r
- assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");\r
- return I->second;\r
-}\r
-\r
-SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) {\r
- if (ID < NUM_PREDEF_DECL_IDS)\r
- return SourceLocation();\r
- \r
- unsigned Index = ID - NUM_PREDEF_DECL_IDS;\r
-\r
- if (Index > DeclsLoaded.size()) {\r
- Error("declaration ID out-of-range for AST file");\r
- return SourceLocation();\r
- }\r
- \r
- if (Decl *D = DeclsLoaded[Index])\r
- return D->getLocation();\r
-\r
- unsigned RawLocation = 0;\r
- RecordLocation Rec = DeclCursorForID(ID, RawLocation);\r
- return ReadSourceLocation(*Rec.F, RawLocation);\r
-}\r
-\r
-Decl *ASTReader::GetDecl(DeclID ID) {\r
- if (ID < NUM_PREDEF_DECL_IDS) { \r
- switch ((PredefinedDeclIDs)ID) {\r
- case PREDEF_DECL_NULL_ID:\r
- return 0;\r
- \r
- case PREDEF_DECL_TRANSLATION_UNIT_ID:\r
- return Context.getTranslationUnitDecl();\r
- \r
- case PREDEF_DECL_OBJC_ID_ID:\r
- return Context.getObjCIdDecl();\r
-\r
- case PREDEF_DECL_OBJC_SEL_ID:\r
- return Context.getObjCSelDecl();\r
-\r
- case PREDEF_DECL_OBJC_CLASS_ID:\r
- return Context.getObjCClassDecl();\r
- \r
- case PREDEF_DECL_OBJC_PROTOCOL_ID:\r
- return Context.getObjCProtocolDecl();\r
- \r
- case PREDEF_DECL_INT_128_ID:\r
- return Context.getInt128Decl();\r
-\r
- case PREDEF_DECL_UNSIGNED_INT_128_ID:\r
- return Context.getUInt128Decl();\r
- \r
- case PREDEF_DECL_OBJC_INSTANCETYPE_ID:\r
- return Context.getObjCInstanceTypeDecl();\r
-\r
- case PREDEF_DECL_BUILTIN_VA_LIST_ID:\r
- return Context.getBuiltinVaListDecl();\r
- }\r
- }\r
- \r
- unsigned Index = ID - NUM_PREDEF_DECL_IDS;\r
-\r
- if (Index >= DeclsLoaded.size()) {\r
- assert(0 && "declaration ID out-of-range for AST file");\r
- Error("declaration ID out-of-range for AST file");\r
- return 0;\r
- }\r
- \r
- if (!DeclsLoaded[Index]) {\r
- ReadDeclRecord(ID);\r
- if (DeserializationListener)\r
- DeserializationListener->DeclRead(ID, DeclsLoaded[Index]);\r
- }\r
-\r
- return DeclsLoaded[Index];\r
-}\r
-\r
-DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M, \r
- DeclID GlobalID) {\r
- if (GlobalID < NUM_PREDEF_DECL_IDS)\r
- return GlobalID;\r
- \r
- GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID);\r
- assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");\r
- ModuleFile *Owner = I->second;\r
-\r
- llvm::DenseMap<ModuleFile *, serialization::DeclID>::iterator Pos\r
- = M.GlobalToLocalDeclIDs.find(Owner);\r
- if (Pos == M.GlobalToLocalDeclIDs.end())\r
- return 0;\r
- \r
- return GlobalID - Owner->BaseDeclID + Pos->second;\r
-}\r
-\r
-serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F, \r
- const RecordData &Record,\r
- unsigned &Idx) {\r
- if (Idx >= Record.size()) {\r
- Error("Corrupted AST file");\r
- return 0;\r
- }\r
- \r
- return getGlobalDeclID(F, Record[Idx++]);\r
-}\r
-\r
-/// \brief Resolve the offset of a statement into a statement.\r
-///\r
-/// This operation will read a new statement from the external\r
-/// source each time it is called, and is meant to be used via a\r
-/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).\r
-Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) {\r
- // Switch case IDs are per Decl.\r
- ClearSwitchCaseIDs();\r
-\r
- // Offset here is a global offset across the entire chain.\r
- RecordLocation Loc = getLocalBitOffset(Offset);\r
- Loc.F->DeclsCursor.JumpToBit(Loc.Offset);\r
- return ReadStmtFromStream(*Loc.F);\r
-}\r
-\r
-namespace {\r
- class FindExternalLexicalDeclsVisitor {\r
- ASTReader &Reader;\r
- const DeclContext *DC;\r
- bool (*isKindWeWant)(Decl::Kind);\r
- \r
- SmallVectorImpl<Decl*> &Decls;\r
- bool PredefsVisited[NUM_PREDEF_DECL_IDS];\r
-\r
- public:\r
- FindExternalLexicalDeclsVisitor(ASTReader &Reader, const DeclContext *DC,\r
- bool (*isKindWeWant)(Decl::Kind),\r
- SmallVectorImpl<Decl*> &Decls)\r
- : Reader(Reader), DC(DC), isKindWeWant(isKindWeWant), Decls(Decls) \r
- {\r
- for (unsigned I = 0; I != NUM_PREDEF_DECL_IDS; ++I)\r
- PredefsVisited[I] = false;\r
- }\r
-\r
- static bool visit(ModuleFile &M, bool Preorder, void *UserData) {\r
- if (Preorder)\r
- return false;\r
-\r
- FindExternalLexicalDeclsVisitor *This\r
- = static_cast<FindExternalLexicalDeclsVisitor *>(UserData);\r
-\r
- ModuleFile::DeclContextInfosMap::iterator Info\r
- = M.DeclContextInfos.find(This->DC);\r
- if (Info == M.DeclContextInfos.end() || !Info->second.LexicalDecls)\r
- return false;\r
-\r
- // Load all of the declaration IDs\r
- for (const KindDeclIDPair *ID = Info->second.LexicalDecls,\r
- *IDE = ID + Info->second.NumLexicalDecls; \r
- ID != IDE; ++ID) {\r
- if (This->isKindWeWant && !This->isKindWeWant((Decl::Kind)ID->first))\r
- continue;\r
-\r
- // Don't add predefined declarations to the lexical context more\r
- // than once.\r
- if (ID->second < NUM_PREDEF_DECL_IDS) {\r
- if (This->PredefsVisited[ID->second])\r
- continue;\r
-\r
- This->PredefsVisited[ID->second] = true;\r
- }\r
-\r
- if (Decl *D = This->Reader.GetLocalDecl(M, ID->second)) {\r
- if (!This->DC->isDeclInLexicalTraversal(D))\r
- This->Decls.push_back(D);\r
- }\r
- }\r
-\r
- return false;\r
- }\r
- };\r
-}\r
-\r
-ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC,\r
- bool (*isKindWeWant)(Decl::Kind),\r
- SmallVectorImpl<Decl*> &Decls) {\r
- // There might be lexical decls in multiple modules, for the TU at\r
- // least. Walk all of the modules in the order they were loaded.\r
- FindExternalLexicalDeclsVisitor Visitor(*this, DC, isKindWeWant, Decls);\r
- ModuleMgr.visitDepthFirst(&FindExternalLexicalDeclsVisitor::visit, &Visitor);\r
- ++NumLexicalDeclContextsRead;\r
- return ELR_Success;\r
-}\r
-\r
-namespace {\r
-\r
-class DeclIDComp {\r
- ASTReader &Reader;\r
- ModuleFile &Mod;\r
-\r
-public:\r
- DeclIDComp(ASTReader &Reader, ModuleFile &M) : Reader(Reader), Mod(M) {}\r
-\r
- bool operator()(LocalDeclID L, LocalDeclID R) const {\r
- SourceLocation LHS = getLocation(L);\r
- SourceLocation RHS = getLocation(R);\r
- return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);\r
- }\r
-\r
- bool operator()(SourceLocation LHS, LocalDeclID R) const {\r
- SourceLocation RHS = getLocation(R);\r
- return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);\r
- }\r
-\r
- bool operator()(LocalDeclID L, SourceLocation RHS) const {\r
- SourceLocation LHS = getLocation(L);\r
- return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);\r
- }\r
-\r
- SourceLocation getLocation(LocalDeclID ID) const {\r
- return Reader.getSourceManager().getFileLoc(\r
- Reader.getSourceLocationForDeclID(Reader.getGlobalDeclID(Mod, ID)));\r
- }\r
-};\r
-\r
-}\r
-\r
-void ASTReader::FindFileRegionDecls(FileID File,\r
- unsigned Offset, unsigned Length,\r
- SmallVectorImpl<Decl *> &Decls) {\r
- SourceManager &SM = getSourceManager();\r
-\r
- llvm::DenseMap<FileID, FileDeclsInfo>::iterator I = FileDeclIDs.find(File);\r
- if (I == FileDeclIDs.end())\r
- return;\r
-\r
- FileDeclsInfo &DInfo = I->second;\r
- if (DInfo.Decls.empty())\r
- return;\r
-\r
- SourceLocation\r
- BeginLoc = SM.getLocForStartOfFile(File).getLocWithOffset(Offset);\r
- SourceLocation EndLoc = BeginLoc.getLocWithOffset(Length);\r
-\r
- DeclIDComp DIDComp(*this, *DInfo.Mod);\r
- ArrayRef<serialization::LocalDeclID>::iterator\r
- BeginIt = std::lower_bound(DInfo.Decls.begin(), DInfo.Decls.end(),\r
- BeginLoc, DIDComp);\r
- if (BeginIt != DInfo.Decls.begin())\r
- --BeginIt;\r
-\r
- // If we are pointing at a top-level decl inside an objc container, we need\r
- // to backtrack until we find it otherwise we will fail to report that the\r
- // region overlaps with an objc container.\r
- while (BeginIt != DInfo.Decls.begin() &&\r
- GetDecl(getGlobalDeclID(*DInfo.Mod, *BeginIt))\r
- ->isTopLevelDeclInObjCContainer())\r
- --BeginIt;\r
-\r
- ArrayRef<serialization::LocalDeclID>::iterator\r
- EndIt = std::upper_bound(DInfo.Decls.begin(), DInfo.Decls.end(),\r
- EndLoc, DIDComp);\r
- if (EndIt != DInfo.Decls.end())\r
- ++EndIt;\r
- \r
- for (ArrayRef<serialization::LocalDeclID>::iterator\r
- DIt = BeginIt; DIt != EndIt; ++DIt)\r
- Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt)));\r
-}\r
-\r
-namespace {\r
- /// \brief ModuleFile visitor used to perform name lookup into a\r
- /// declaration context.\r
- class DeclContextNameLookupVisitor {\r
- ASTReader &Reader;\r
- llvm::SmallVectorImpl<const DeclContext *> &Contexts;\r
- DeclarationName Name;\r
- SmallVectorImpl<NamedDecl *> &Decls;\r
-\r
- public:\r
- DeclContextNameLookupVisitor(ASTReader &Reader, \r
- SmallVectorImpl<const DeclContext *> &Contexts, \r
- DeclarationName Name,\r
- SmallVectorImpl<NamedDecl *> &Decls)\r
- : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { }\r
-\r
- static bool visit(ModuleFile &M, void *UserData) {\r
- DeclContextNameLookupVisitor *This\r
- = static_cast<DeclContextNameLookupVisitor *>(UserData);\r
-\r
- // Check whether we have any visible declaration information for\r
- // this context in this module.\r
- ModuleFile::DeclContextInfosMap::iterator Info;\r
- bool FoundInfo = false;\r
- for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {\r
- Info = M.DeclContextInfos.find(This->Contexts[I]);\r
- if (Info != M.DeclContextInfos.end() && \r
- Info->second.NameLookupTableData) {\r
- FoundInfo = true;\r
- break;\r
- }\r
- }\r
-\r
- if (!FoundInfo)\r
- return false;\r
- \r
- // Look for this name within this module.\r
- ASTDeclContextNameLookupTable *LookupTable =\r
- Info->second.NameLookupTableData;\r
- ASTDeclContextNameLookupTable::iterator Pos\r
- = LookupTable->find(This->Name);\r
- if (Pos == LookupTable->end())\r
- return false;\r
-\r
- bool FoundAnything = false;\r
- ASTDeclContextNameLookupTrait::data_type Data = *Pos;\r
- for (; Data.first != Data.second; ++Data.first) {\r
- NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M, *Data.first);\r
- if (!ND)\r
- continue;\r
-\r
- if (ND->getDeclName() != This->Name) {\r
- // A name might be null because the decl's redeclarable part is\r
- // currently read before reading its name. The lookup is triggered by\r
- // building that decl (likely indirectly), and so it is later in the\r
- // sense of "already existing" and can be ignored here.\r
- continue;\r
- }\r
- \r
- // Record this declaration.\r
- FoundAnything = true;\r
- This->Decls.push_back(ND);\r
- }\r
-\r
- return FoundAnything;\r
- }\r
- };\r
-}\r
-\r
-DeclContext::lookup_result\r
-ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,\r
- DeclarationName Name) {\r
- assert(DC->hasExternalVisibleStorage() &&\r
- "DeclContext has no visible decls in storage");\r
- if (!Name)\r
- return DeclContext::lookup_result(DeclContext::lookup_iterator(0),\r
- DeclContext::lookup_iterator(0));\r
-\r
- SmallVector<NamedDecl *, 64> Decls;\r
- \r
- // Compute the declaration contexts we need to look into. Multiple such\r
- // declaration contexts occur when two declaration contexts from disjoint\r
- // modules get merged, e.g., when two namespaces with the same name are \r
- // independently defined in separate modules.\r
- SmallVector<const DeclContext *, 2> Contexts;\r
- Contexts.push_back(DC);\r
- \r
- if (DC->isNamespace()) {\r
- MergedDeclsMap::iterator Merged\r
- = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));\r
- if (Merged != MergedDecls.end()) {\r
- for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)\r
- Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));\r
- }\r
- }\r
- \r
- DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);\r
- ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);\r
- ++NumVisibleDeclContextsRead;\r
- SetExternalVisibleDeclsForName(DC, Name, Decls);\r
- return const_cast<DeclContext*>(DC)->lookup(Name);\r
-}\r
-\r
-namespace {\r
- /// \brief ModuleFile visitor used to retrieve all visible names in a\r
- /// declaration context.\r
- class DeclContextAllNamesVisitor {\r
- ASTReader &Reader;\r
- llvm::SmallVectorImpl<const DeclContext *> &Contexts;\r
- llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> > &Decls;\r
-\r
- public:\r
- DeclContextAllNamesVisitor(ASTReader &Reader,\r
- SmallVectorImpl<const DeclContext *> &Contexts,\r
- llvm::DenseMap<DeclarationName,\r
- SmallVector<NamedDecl *, 8> > &Decls)\r
- : Reader(Reader), Contexts(Contexts), Decls(Decls) { }\r
-\r
- static bool visit(ModuleFile &M, void *UserData) {\r
- DeclContextAllNamesVisitor *This\r
- = static_cast<DeclContextAllNamesVisitor *>(UserData);\r
-\r
- // Check whether we have any visible declaration information for\r
- // this context in this module.\r
- ModuleFile::DeclContextInfosMap::iterator Info;\r
- bool FoundInfo = false;\r
- for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {\r
- Info = M.DeclContextInfos.find(This->Contexts[I]);\r
- if (Info != M.DeclContextInfos.end() &&\r
- Info->second.NameLookupTableData) {\r
- FoundInfo = true;\r
- break;\r
- }\r
- }\r
-\r
- if (!FoundInfo)\r
- return false;\r
-\r
- ASTDeclContextNameLookupTable *LookupTable =\r
- Info->second.NameLookupTableData;\r
- bool FoundAnything = false;\r
- for (ASTDeclContextNameLookupTable::data_iterator\r
- I = LookupTable->data_begin(), E = LookupTable->data_end();\r
- I != E; ++I) {\r
- ASTDeclContextNameLookupTrait::data_type Data = *I;\r
- for (; Data.first != Data.second; ++Data.first) {\r
- NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M,\r
- *Data.first);\r
- if (!ND)\r
- continue;\r
-\r
- // Record this declaration.\r
- FoundAnything = true;\r
- This->Decls[ND->getDeclName()].push_back(ND);\r
- }\r
- }\r
-\r
- return FoundAnything;\r
- }\r
- };\r
-}\r
-\r
-void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {\r
- if (!DC->hasExternalVisibleStorage())\r
- return;\r
- llvm::DenseMap<DeclarationName, llvm::SmallVector<NamedDecl*, 8> > Decls;\r
-\r
- // Compute the declaration contexts we need to look into. Multiple such\r
- // declaration contexts occur when two declaration contexts from disjoint\r
- // modules get merged, e.g., when two namespaces with the same name are\r
- // independently defined in separate modules.\r
- SmallVector<const DeclContext *, 2> Contexts;\r
- Contexts.push_back(DC);\r
-\r
- if (DC->isNamespace()) {\r
- MergedDeclsMap::iterator Merged\r
- = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));\r
- if (Merged != MergedDecls.end()) {\r
- for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)\r
- Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));\r
- }\r
- }\r
-\r
- DeclContextAllNamesVisitor Visitor(*this, Contexts, Decls);\r
- ModuleMgr.visit(&DeclContextAllNamesVisitor::visit, &Visitor);\r
- ++NumVisibleDeclContextsRead;\r
-\r
- for (llvm::DenseMap<DeclarationName,\r
- llvm::SmallVector<NamedDecl*, 8> >::iterator\r
- I = Decls.begin(), E = Decls.end(); I != E; ++I) {\r
- SetExternalVisibleDeclsForName(DC, I->first, I->second);\r
- }\r
- const_cast<DeclContext *>(DC)->setHasExternalVisibleStorage(false);\r
-}\r
-\r
-/// \brief Under non-PCH compilation the consumer receives the objc methods\r
-/// before receiving the implementation, and codegen depends on this.\r
-/// We simulate this by deserializing and passing to consumer the methods of the\r
-/// implementation before passing the deserialized implementation decl.\r
-static void PassObjCImplDeclToConsumer(ObjCImplDecl *ImplD,\r
- ASTConsumer *Consumer) {\r
- assert(ImplD && Consumer);\r
-\r
- for (ObjCImplDecl::method_iterator\r
- I = ImplD->meth_begin(), E = ImplD->meth_end(); I != E; ++I)\r
- Consumer->HandleInterestingDecl(DeclGroupRef(*I));\r
-\r
- Consumer->HandleInterestingDecl(DeclGroupRef(ImplD));\r
-}\r
-\r
-void ASTReader::PassInterestingDeclsToConsumer() {\r
- assert(Consumer);\r
- while (!InterestingDecls.empty()) {\r
- Decl *D = InterestingDecls.front();\r
- InterestingDecls.pop_front();\r
-\r
- PassInterestingDeclToConsumer(D);\r
- }\r
-}\r
-\r
-void ASTReader::PassInterestingDeclToConsumer(Decl *D) {\r
- if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D))\r
- PassObjCImplDeclToConsumer(ImplD, Consumer);\r
- else\r
- Consumer->HandleInterestingDecl(DeclGroupRef(D));\r
-}\r
-\r
-void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {\r
- this->Consumer = Consumer;\r
-\r
- if (!Consumer)\r
- return;\r
-\r
- for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {\r
- // Force deserialization of this decl, which will cause it to be queued for\r
- // passing to the consumer.\r
- GetDecl(ExternalDefinitions[I]);\r
- }\r
- ExternalDefinitions.clear();\r
-\r
- PassInterestingDeclsToConsumer();\r
-}\r
-\r
-void ASTReader::PrintStats() {\r
- std::fprintf(stderr, "*** AST File Statistics:\n");\r
-\r
- unsigned NumTypesLoaded\r
- = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),\r
- QualType());\r
- unsigned NumDeclsLoaded\r
- = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),\r
- (Decl *)0);\r
- unsigned NumIdentifiersLoaded\r
- = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),\r
- IdentifiersLoaded.end(),\r
- (IdentifierInfo *)0);\r
- unsigned NumMacrosLoaded\r
- = MacrosLoaded.size() - std::count(MacrosLoaded.begin(),\r
- MacrosLoaded.end(),\r
- (MacroInfo *)0);\r
- unsigned NumSelectorsLoaded\r
- = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),\r
- SelectorsLoaded.end(),\r
- Selector());\r
-\r
- if (unsigned TotalNumSLocEntries = getTotalNumSLocs())\r
- std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",\r
- NumSLocEntriesRead, TotalNumSLocEntries,\r
- ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));\r
- if (!TypesLoaded.empty())\r
- std::fprintf(stderr, " %u/%u types read (%f%%)\n",\r
- NumTypesLoaded, (unsigned)TypesLoaded.size(),\r
- ((float)NumTypesLoaded/TypesLoaded.size() * 100));\r
- if (!DeclsLoaded.empty())\r
- std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",\r
- NumDeclsLoaded, (unsigned)DeclsLoaded.size(),\r
- ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));\r
- if (!IdentifiersLoaded.empty())\r
- std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",\r
- NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),\r
- ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));\r
- if (!MacrosLoaded.empty())\r
- std::fprintf(stderr, " %u/%u macros read (%f%%)\n",\r
- NumMacrosLoaded, (unsigned)MacrosLoaded.size(),\r
- ((float)NumMacrosLoaded/MacrosLoaded.size() * 100));\r
- if (!SelectorsLoaded.empty())\r
- std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",\r
- NumSelectorsLoaded, (unsigned)SelectorsLoaded.size(),\r
- ((float)NumSelectorsLoaded/SelectorsLoaded.size() * 100));\r
- if (TotalNumStatements)\r
- std::fprintf(stderr, " %u/%u statements read (%f%%)\n",\r
- NumStatementsRead, TotalNumStatements,\r
- ((float)NumStatementsRead/TotalNumStatements * 100));\r
- if (TotalNumMacros)\r
- std::fprintf(stderr, " %u/%u macros read (%f%%)\n",\r
- NumMacrosRead, TotalNumMacros,\r
- ((float)NumMacrosRead/TotalNumMacros * 100));\r
- if (TotalLexicalDeclContexts)\r
- std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n",\r
- NumLexicalDeclContextsRead, TotalLexicalDeclContexts,\r
- ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts\r
- * 100));\r
- if (TotalVisibleDeclContexts)\r
- std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n",\r
- NumVisibleDeclContextsRead, TotalVisibleDeclContexts,\r
- ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts\r
- * 100));\r
- if (TotalNumMethodPoolEntries) {\r
- std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",\r
- NumMethodPoolEntriesRead, TotalNumMethodPoolEntries,\r
- ((float)NumMethodPoolEntriesRead/TotalNumMethodPoolEntries\r
- * 100));\r
- std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses);\r
- }\r
- std::fprintf(stderr, "\n");\r
- dump();\r
- std::fprintf(stderr, "\n");\r
-}\r
-\r
-template<typename Key, typename ModuleFile, unsigned InitialCapacity>\r
-static void \r
-dumpModuleIDMap(StringRef Name,\r
- const ContinuousRangeMap<Key, ModuleFile *, \r
- InitialCapacity> &Map) {\r
- if (Map.begin() == Map.end())\r
- return;\r
- \r
- typedef ContinuousRangeMap<Key, ModuleFile *, InitialCapacity> MapType;\r
- llvm::errs() << Name << ":\n";\r
- for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end(); \r
- I != IEnd; ++I) {\r
- llvm::errs() << " " << I->first << " -> " << I->second->FileName\r
- << "\n";\r
- }\r
-}\r
-\r
-void ASTReader::dump() {\r
- llvm::errs() << "*** PCH/ModuleFile Remappings:\n";\r
- dumpModuleIDMap("Global bit offset map", GlobalBitOffsetsMap);\r
- dumpModuleIDMap("Global source location entry map", GlobalSLocEntryMap);\r
- dumpModuleIDMap("Global type map", GlobalTypeMap);\r
- dumpModuleIDMap("Global declaration map", GlobalDeclMap);\r
- dumpModuleIDMap("Global identifier map", GlobalIdentifierMap);\r
- dumpModuleIDMap("Global macro map", GlobalMacroMap);\r
- dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap);\r
- dumpModuleIDMap("Global selector map", GlobalSelectorMap);\r
- dumpModuleIDMap("Global preprocessed entity map", \r
- GlobalPreprocessedEntityMap);\r
- \r
- llvm::errs() << "\n*** PCH/Modules Loaded:";\r
- for (ModuleManager::ModuleConstIterator M = ModuleMgr.begin(), \r
- MEnd = ModuleMgr.end();\r
- M != MEnd; ++M)\r
- (*M)->dump();\r
-}\r
-\r
-/// Return the amount of memory used by memory buffers, breaking down\r
-/// by heap-backed versus mmap'ed memory.\r
-void ASTReader::getMemoryBufferSizes(MemoryBufferSizes &sizes) const {\r
- for (ModuleConstIterator I = ModuleMgr.begin(),\r
- E = ModuleMgr.end(); I != E; ++I) {\r
- if (llvm::MemoryBuffer *buf = (*I)->Buffer.get()) {\r
- size_t bytes = buf->getBufferSize();\r
- switch (buf->getBufferKind()) {\r
- case llvm::MemoryBuffer::MemoryBuffer_Malloc:\r
- sizes.malloc_bytes += bytes;\r
- break;\r
- case llvm::MemoryBuffer::MemoryBuffer_MMap:\r
- sizes.mmap_bytes += bytes;\r
- break;\r
- }\r
- }\r
- }\r
-}\r
-\r
-void ASTReader::InitializeSema(Sema &S) {\r
- SemaObj = &S;\r
- S.addExternalSource(this);\r
-\r
- // Makes sure any declarations that were deserialized "too early"\r
- // still get added to the identifier's declaration chains.\r
- for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {\r
- SemaObj->pushExternalDeclIntoScope(PreloadedDecls[I], \r
- PreloadedDecls[I]->getDeclName());\r
- }\r
- PreloadedDecls.clear();\r
-\r
- // Load the offsets of the declarations that Sema references.\r
- // They will be lazily deserialized when needed.\r
- if (!SemaDeclRefs.empty()) {\r
- assert(SemaDeclRefs.size() == 2 && "More decl refs than expected!");\r
- if (!SemaObj->StdNamespace)\r
- SemaObj->StdNamespace = SemaDeclRefs[0];\r
- if (!SemaObj->StdBadAlloc)\r
- SemaObj->StdBadAlloc = SemaDeclRefs[1];\r
- }\r
-\r
- if (!FPPragmaOptions.empty()) {\r
- assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS");\r
- SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0];\r
- }\r
-\r
- if (!OpenCLExtensions.empty()) {\r
- unsigned I = 0;\r
-#define OPENCLEXT(nm) SemaObj->OpenCLFeatures.nm = OpenCLExtensions[I++];\r
-#include "clang/Basic/OpenCLExtensions.def"\r
-\r
- assert(OpenCLExtensions.size() == I && "Wrong number of OPENCL_EXTENSIONS");\r
- }\r
-}\r
-\r
-IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {\r
- // Note that we are loading an identifier.\r
- Deserializing AnIdentifier(this);\r
- \r
- IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart),\r
- /*PriorGeneration=*/0);\r
- ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);\r
- IdentifierInfo *II = Visitor.getIdentifierInfo();\r
- markIdentifierUpToDate(II);\r
- return II;\r
-}\r
-\r
-namespace clang {\r
- /// \brief An identifier-lookup iterator that enumerates all of the\r
- /// identifiers stored within a set of AST files.\r
- class ASTIdentifierIterator : public IdentifierIterator {\r
- /// \brief The AST reader whose identifiers are being enumerated.\r
- const ASTReader &Reader;\r
-\r
- /// \brief The current index into the chain of AST files stored in\r
- /// the AST reader.\r
- unsigned Index;\r
-\r
- /// \brief The current position within the identifier lookup table\r
- /// of the current AST file.\r
- ASTIdentifierLookupTable::key_iterator Current;\r
-\r
- /// \brief The end position within the identifier lookup table of\r
- /// the current AST file.\r
- ASTIdentifierLookupTable::key_iterator End;\r
-\r
- public:\r
- explicit ASTIdentifierIterator(const ASTReader &Reader);\r
-\r
- virtual StringRef Next();\r
- };\r
-}\r
-\r
-ASTIdentifierIterator::ASTIdentifierIterator(const ASTReader &Reader)\r
- : Reader(Reader), Index(Reader.ModuleMgr.size() - 1) {\r
- ASTIdentifierLookupTable *IdTable\r
- = (ASTIdentifierLookupTable *)Reader.ModuleMgr[Index].IdentifierLookupTable;\r
- Current = IdTable->key_begin();\r
- End = IdTable->key_end();\r
-}\r
-\r
-StringRef ASTIdentifierIterator::Next() {\r
- while (Current == End) {\r
- // If we have exhausted all of our AST files, we're done.\r
- if (Index == 0)\r
- return StringRef();\r
-\r
- --Index;\r
- ASTIdentifierLookupTable *IdTable\r
- = (ASTIdentifierLookupTable *)Reader.ModuleMgr[Index].\r
- IdentifierLookupTable;\r
- Current = IdTable->key_begin();\r
- End = IdTable->key_end();\r
- }\r
-\r
- // We have any identifiers remaining in the current AST file; return\r
- // the next one.\r
- std::pair<const char*, unsigned> Key = *Current;\r
- ++Current;\r
- return StringRef(Key.first, Key.second);\r
-}\r
-\r
-IdentifierIterator *ASTReader::getIdentifiers() const {\r
- return new ASTIdentifierIterator(*this);\r
-}\r
-\r
-namespace clang { namespace serialization {\r
- class ReadMethodPoolVisitor {\r
- ASTReader &Reader;\r
- Selector Sel;\r
- unsigned PriorGeneration;\r
- llvm::SmallVector<ObjCMethodDecl *, 4> InstanceMethods;\r
- llvm::SmallVector<ObjCMethodDecl *, 4> FactoryMethods;\r
-\r
- public:\r
- ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel, \r
- unsigned PriorGeneration)\r
- : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration) { }\r
- \r
- static bool visit(ModuleFile &M, void *UserData) {\r
- ReadMethodPoolVisitor *This\r
- = static_cast<ReadMethodPoolVisitor *>(UserData);\r
- \r
- if (!M.SelectorLookupTable)\r
- return false;\r
- \r
- // If we've already searched this module file, skip it now.\r
- if (M.Generation <= This->PriorGeneration)\r
- return true;\r
-\r
- ASTSelectorLookupTable *PoolTable\r
- = (ASTSelectorLookupTable*)M.SelectorLookupTable;\r
- ASTSelectorLookupTable::iterator Pos = PoolTable->find(This->Sel);\r
- if (Pos == PoolTable->end())\r
- return false;\r
- \r
- ++This->Reader.NumSelectorsRead;\r
- // FIXME: Not quite happy with the statistics here. We probably should\r
- // disable this tracking when called via LoadSelector.\r
- // Also, should entries without methods count as misses?\r
- ++This->Reader.NumMethodPoolEntriesRead;\r
- ASTSelectorLookupTrait::data_type Data = *Pos;\r
- if (This->Reader.DeserializationListener)\r
- This->Reader.DeserializationListener->SelectorRead(Data.ID, \r
- This->Sel);\r
- \r
- This->InstanceMethods.append(Data.Instance.begin(), Data.Instance.end());\r
- This->FactoryMethods.append(Data.Factory.begin(), Data.Factory.end());\r
- return true;\r
- }\r
- \r
- /// \brief Retrieve the instance methods found by this visitor.\r
- ArrayRef<ObjCMethodDecl *> getInstanceMethods() const { \r
- return InstanceMethods; \r
- }\r
-\r
- /// \brief Retrieve the instance methods found by this visitor.\r
- ArrayRef<ObjCMethodDecl *> getFactoryMethods() const { \r
- return FactoryMethods;\r
- }\r
- };\r
-} } // end namespace clang::serialization\r
-\r
-/// \brief Add the given set of methods to the method list.\r
-static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods,\r
- ObjCMethodList &List) {\r
- for (unsigned I = 0, N = Methods.size(); I != N; ++I) {\r
- S.addMethodToGlobalList(&List, Methods[I]);\r
- }\r
-}\r
- \r
-void ASTReader::ReadMethodPool(Selector Sel) {\r
- // Get the selector generation and update it to the current generation.\r
- unsigned &Generation = SelectorGeneration[Sel];\r
- unsigned PriorGeneration = Generation;\r
- Generation = CurrentGeneration;\r
- \r
- // Search for methods defined with this selector.\r
- ReadMethodPoolVisitor Visitor(*this, Sel, PriorGeneration);\r
- ModuleMgr.visit(&ReadMethodPoolVisitor::visit, &Visitor);\r
- \r
- if (Visitor.getInstanceMethods().empty() &&\r
- Visitor.getFactoryMethods().empty()) {\r
- ++NumMethodPoolMisses;\r
- return;\r
- }\r
- \r
- if (!getSema())\r
- return;\r
- \r
- Sema &S = *getSema();\r
- Sema::GlobalMethodPool::iterator Pos\r
- = S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethods())).first;\r
- \r
- addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first);\r
- addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second);\r
-}\r
-\r
-void ASTReader::ReadKnownNamespaces(\r
- SmallVectorImpl<NamespaceDecl *> &Namespaces) {\r
- Namespaces.clear();\r
- \r
- for (unsigned I = 0, N = KnownNamespaces.size(); I != N; ++I) {\r
- if (NamespaceDecl *Namespace \r
- = dyn_cast_or_null<NamespaceDecl>(GetDecl(KnownNamespaces[I])))\r
- Namespaces.push_back(Namespace);\r
- }\r
-}\r
-\r
-void ASTReader::ReadTentativeDefinitions(\r
- SmallVectorImpl<VarDecl *> &TentativeDefs) {\r
- for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {\r
- VarDecl *Var = dyn_cast_or_null<VarDecl>(GetDecl(TentativeDefinitions[I]));\r
- if (Var)\r
- TentativeDefs.push_back(Var);\r
- }\r
- TentativeDefinitions.clear();\r
-}\r
-\r
-void ASTReader::ReadUnusedFileScopedDecls(\r
- SmallVectorImpl<const DeclaratorDecl *> &Decls) {\r
- for (unsigned I = 0, N = UnusedFileScopedDecls.size(); I != N; ++I) {\r
- DeclaratorDecl *D\r
- = dyn_cast_or_null<DeclaratorDecl>(GetDecl(UnusedFileScopedDecls[I]));\r
- if (D)\r
- Decls.push_back(D);\r
- }\r
- UnusedFileScopedDecls.clear();\r
-}\r
-\r
-void ASTReader::ReadDelegatingConstructors(\r
- SmallVectorImpl<CXXConstructorDecl *> &Decls) {\r
- for (unsigned I = 0, N = DelegatingCtorDecls.size(); I != N; ++I) {\r
- CXXConstructorDecl *D\r
- = dyn_cast_or_null<CXXConstructorDecl>(GetDecl(DelegatingCtorDecls[I]));\r
- if (D)\r
- Decls.push_back(D);\r
- }\r
- DelegatingCtorDecls.clear();\r
-}\r
-\r
-void ASTReader::ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {\r
- for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) {\r
- TypedefNameDecl *D\r
- = dyn_cast_or_null<TypedefNameDecl>(GetDecl(ExtVectorDecls[I]));\r
- if (D)\r
- Decls.push_back(D);\r
- }\r
- ExtVectorDecls.clear();\r
-}\r
-\r
-void ASTReader::ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) {\r
- for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) {\r
- CXXRecordDecl *D\r
- = dyn_cast_or_null<CXXRecordDecl>(GetDecl(DynamicClasses[I]));\r
- if (D)\r
- Decls.push_back(D);\r
- }\r
- DynamicClasses.clear();\r
-}\r
-\r
-void \r
-ASTReader::ReadLocallyScopedExternalDecls(SmallVectorImpl<NamedDecl *> &Decls) {\r
- for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {\r
- NamedDecl *D \r
- = dyn_cast_or_null<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));\r
- if (D)\r
- Decls.push_back(D);\r
- }\r
- LocallyScopedExternalDecls.clear();\r
-}\r
-\r
-void ASTReader::ReadReferencedSelectors(\r
- SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {\r
- if (ReferencedSelectorsData.empty())\r
- return;\r
- \r
- // If there are @selector references added them to its pool. This is for\r
- // implementation of -Wselector.\r
- unsigned int DataSize = ReferencedSelectorsData.size()-1;\r
- unsigned I = 0;\r
- while (I < DataSize) {\r
- Selector Sel = DecodeSelector(ReferencedSelectorsData[I++]);\r
- SourceLocation SelLoc\r
- = SourceLocation::getFromRawEncoding(ReferencedSelectorsData[I++]);\r
- Sels.push_back(std::make_pair(Sel, SelLoc));\r
- }\r
- ReferencedSelectorsData.clear();\r
-}\r
-\r
-void ASTReader::ReadWeakUndeclaredIdentifiers(\r
- SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WeakIDs) {\r
- if (WeakUndeclaredIdentifiers.empty())\r
- return;\r
-\r
- for (unsigned I = 0, N = WeakUndeclaredIdentifiers.size(); I < N; /*none*/) {\r
- IdentifierInfo *WeakId \r
- = DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]);\r
- IdentifierInfo *AliasId \r
- = DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]);\r
- SourceLocation Loc\r
- = SourceLocation::getFromRawEncoding(WeakUndeclaredIdentifiers[I++]);\r
- bool Used = WeakUndeclaredIdentifiers[I++];\r
- WeakInfo WI(AliasId, Loc);\r
- WI.setUsed(Used);\r
- WeakIDs.push_back(std::make_pair(WeakId, WI));\r
- }\r
- WeakUndeclaredIdentifiers.clear();\r
-}\r
-\r
-void ASTReader::ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {\r
- for (unsigned Idx = 0, N = VTableUses.size(); Idx < N; /* In loop */) {\r
- ExternalVTableUse VT;\r
- VT.Record = dyn_cast_or_null<CXXRecordDecl>(GetDecl(VTableUses[Idx++]));\r
- VT.Location = SourceLocation::getFromRawEncoding(VTableUses[Idx++]);\r
- VT.DefinitionRequired = VTableUses[Idx++];\r
- VTables.push_back(VT);\r
- }\r
- \r
- VTableUses.clear();\r
-}\r
-\r
-void ASTReader::ReadPendingInstantiations(\r
- SmallVectorImpl<std::pair<ValueDecl *, SourceLocation> > &Pending) {\r
- for (unsigned Idx = 0, N = PendingInstantiations.size(); Idx < N;) {\r
- ValueDecl *D = cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++]));\r
- SourceLocation Loc\r
- = SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]);\r
-\r
- Pending.push_back(std::make_pair(D, Loc));\r
- } \r
- PendingInstantiations.clear();\r
-}\r
-\r
-void ASTReader::LoadSelector(Selector Sel) {\r
- // It would be complicated to avoid reading the methods anyway. So don't.\r
- ReadMethodPool(Sel);\r
-}\r
-\r
-void ASTReader::SetIdentifierInfo(IdentifierID ID, IdentifierInfo *II) {\r
- assert(ID && "Non-zero identifier ID required");\r
- assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");\r
- IdentifiersLoaded[ID - 1] = II;\r
- if (DeserializationListener)\r
- DeserializationListener->IdentifierRead(ID, II);\r
-}\r
-\r
-/// \brief Set the globally-visible declarations associated with the given\r
-/// identifier.\r
-///\r
-/// If the AST reader is currently in a state where the given declaration IDs\r
-/// cannot safely be resolved, they are queued until it is safe to resolve\r
-/// them.\r
-///\r
-/// \param II an IdentifierInfo that refers to one or more globally-visible\r
-/// declarations.\r
-///\r
-/// \param DeclIDs the set of declaration IDs with the name @p II that are\r
-/// visible at global scope.\r
-///\r
-/// \param Nonrecursive should be true to indicate that the caller knows that\r
-/// this call is non-recursive, and therefore the globally-visible declarations\r
-/// will not be placed onto the pending queue.\r
-void\r
-ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II,\r
- const SmallVectorImpl<uint32_t> &DeclIDs,\r
- bool Nonrecursive) {\r
- if (NumCurrentElementsDeserializing && !Nonrecursive) {\r
- PendingIdentifierInfos.push_back(PendingIdentifierInfo());\r
- PendingIdentifierInfo &PII = PendingIdentifierInfos.back();\r
- PII.II = II;\r
- PII.DeclIDs.append(DeclIDs.begin(), DeclIDs.end());\r
- return;\r
- }\r
-\r
- for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {\r
- NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));\r
- if (SemaObj) {\r
- // Introduce this declaration into the translation-unit scope\r
- // and add it to the declaration chain for this identifier, so\r
- // that (unqualified) name lookup will find it.\r
- SemaObj->pushExternalDeclIntoScope(D, II);\r
- } else {\r
- // Queue this declaration so that it will be added to the\r
- // translation unit scope and identifier's declaration chain\r
- // once a Sema object is known.\r
- PreloadedDecls.push_back(D);\r
- }\r
- }\r
-}\r
-\r
-IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) {\r
- if (ID == 0)\r
- return 0;\r
-\r
- if (IdentifiersLoaded.empty()) {\r
- Error("no identifier table in AST file");\r
- return 0;\r
- }\r
-\r
- ID -= 1;\r
- if (!IdentifiersLoaded[ID]) {\r
- GlobalIdentifierMapType::iterator I = GlobalIdentifierMap.find(ID + 1);\r
- assert(I != GlobalIdentifierMap.end() && "Corrupted global identifier map");\r
- ModuleFile *M = I->second;\r
- unsigned Index = ID - M->BaseIdentifierID;\r
- const char *Str = M->IdentifierTableData + M->IdentifierOffsets[Index];\r
-\r
- // All of the strings in the AST file are preceded by a 16-bit length.\r
- // Extract that 16-bit length to avoid having to execute strlen().\r
- // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as\r
- // unsigned integers. This is important to avoid integer overflow when\r
- // we cast them to 'unsigned'.\r
- const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;\r
- unsigned StrLen = (((unsigned) StrLenPtr[0])\r
- | (((unsigned) StrLenPtr[1]) << 8)) - 1;\r
- IdentifiersLoaded[ID]\r
- = &PP.getIdentifierTable().get(StringRef(Str, StrLen));\r
- if (DeserializationListener)\r
- DeserializationListener->IdentifierRead(ID + 1, IdentifiersLoaded[ID]);\r
- }\r
-\r
- return IdentifiersLoaded[ID];\r
-}\r
-\r
-IdentifierInfo *ASTReader::getLocalIdentifier(ModuleFile &M, unsigned LocalID) {\r
- return DecodeIdentifierInfo(getGlobalIdentifierID(M, LocalID));\r
-}\r
-\r
-IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) {\r
- if (LocalID < NUM_PREDEF_IDENT_IDS)\r
- return LocalID;\r
- \r
- ContinuousRangeMap<uint32_t, int, 2>::iterator I\r
- = M.IdentifierRemap.find(LocalID - NUM_PREDEF_IDENT_IDS);\r
- assert(I != M.IdentifierRemap.end() \r
- && "Invalid index into identifier index remap");\r
- \r
- return LocalID + I->second;\r
-}\r
-\r
-MacroInfo *ASTReader::getMacro(MacroID ID, MacroInfo *Hint) {\r
- if (ID == 0)\r
- return 0;\r
-\r
- if (MacrosLoaded.empty()) {\r
- Error("no macro table in AST file");\r
- return 0;\r
- }\r
-\r
- ID -= NUM_PREDEF_MACRO_IDS;\r
- if (!MacrosLoaded[ID]) {\r
- GlobalMacroMapType::iterator I\r
- = GlobalMacroMap.find(ID + NUM_PREDEF_MACRO_IDS);\r
- assert(I != GlobalMacroMap.end() && "Corrupted global macro map");\r
- ModuleFile *M = I->second;\r
- unsigned Index = ID - M->BaseMacroID;\r
- ReadMacroRecord(*M, M->MacroOffsets[Index], Hint);\r
- }\r
-\r
- return MacrosLoaded[ID];\r
-}\r
-\r
-MacroID ASTReader::getGlobalMacroID(ModuleFile &M, unsigned LocalID) {\r
- if (LocalID < NUM_PREDEF_MACRO_IDS)\r
- return LocalID;\r
-\r
- ContinuousRangeMap<uint32_t, int, 2>::iterator I\r
- = M.MacroRemap.find(LocalID - NUM_PREDEF_MACRO_IDS);\r
- assert(I != M.MacroRemap.end() && "Invalid index into macro index remap");\r
-\r
- return LocalID + I->second;\r
-}\r
-\r
-serialization::SubmoduleID\r
-ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) {\r
- if (LocalID < NUM_PREDEF_SUBMODULE_IDS)\r
- return LocalID;\r
- \r
- ContinuousRangeMap<uint32_t, int, 2>::iterator I\r
- = M.SubmoduleRemap.find(LocalID - NUM_PREDEF_SUBMODULE_IDS);\r
- assert(I != M.SubmoduleRemap.end() \r
- && "Invalid index into submodule index remap");\r
- \r
- return LocalID + I->second;\r
-}\r
-\r
-Module *ASTReader::getSubmodule(SubmoduleID GlobalID) {\r
- if (GlobalID < NUM_PREDEF_SUBMODULE_IDS) {\r
- assert(GlobalID == 0 && "Unhandled global submodule ID");\r
- return 0;\r
- }\r
- \r
- if (GlobalID > SubmodulesLoaded.size()) {\r
- Error("submodule ID out of range in AST file");\r
- return 0;\r
- }\r
- \r
- return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS];\r
-}\r
- \r
-Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) {\r
- return DecodeSelector(getGlobalSelectorID(M, LocalID));\r
-}\r
-\r
-Selector ASTReader::DecodeSelector(serialization::SelectorID ID) {\r
- if (ID == 0)\r
- return Selector();\r
-\r
- if (ID > SelectorsLoaded.size()) {\r
- Error("selector ID out of range in AST file");\r
- return Selector();\r
- }\r
-\r
- if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) {\r
- // Load this selector from the selector table.\r
- GlobalSelectorMapType::iterator I = GlobalSelectorMap.find(ID);\r
- assert(I != GlobalSelectorMap.end() && "Corrupted global selector map");\r
- ModuleFile &M = *I->second;\r
- ASTSelectorLookupTrait Trait(*this, M);\r
- unsigned Idx = ID - M.BaseSelectorID - NUM_PREDEF_SELECTOR_IDS;\r
- SelectorsLoaded[ID - 1] =\r
- Trait.ReadKey(M.SelectorLookupTableData + M.SelectorOffsets[Idx], 0);\r
- if (DeserializationListener)\r
- DeserializationListener->SelectorRead(ID, SelectorsLoaded[ID - 1]);\r
- }\r
-\r
- return SelectorsLoaded[ID - 1];\r
-}\r
-\r
-Selector ASTReader::GetExternalSelector(serialization::SelectorID ID) {\r
- return DecodeSelector(ID);\r
-}\r
-\r
-uint32_t ASTReader::GetNumExternalSelectors() {\r
- // ID 0 (the null selector) is considered an external selector.\r
- return getTotalNumSelectors() + 1;\r
-}\r
-\r
-serialization::SelectorID\r
-ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const {\r
- if (LocalID < NUM_PREDEF_SELECTOR_IDS)\r
- return LocalID;\r
- \r
- ContinuousRangeMap<uint32_t, int, 2>::iterator I\r
- = M.SelectorRemap.find(LocalID - NUM_PREDEF_SELECTOR_IDS);\r
- assert(I != M.SelectorRemap.end() \r
- && "Invalid index into selector index remap");\r
- \r
- return LocalID + I->second;\r
-}\r
-\r
-DeclarationName\r
-ASTReader::ReadDeclarationName(ModuleFile &F, \r
- const RecordData &Record, unsigned &Idx) {\r
- DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];\r
- switch (Kind) {\r
- case DeclarationName::Identifier:\r
- return DeclarationName(GetIdentifierInfo(F, Record, Idx));\r
-\r
- case DeclarationName::ObjCZeroArgSelector:\r
- case DeclarationName::ObjCOneArgSelector:\r
- case DeclarationName::ObjCMultiArgSelector:\r
- return DeclarationName(ReadSelector(F, Record, Idx));\r
-\r
- case DeclarationName::CXXConstructorName:\r
- return Context.DeclarationNames.getCXXConstructorName(\r
- Context.getCanonicalType(readType(F, Record, Idx)));\r
-\r
- case DeclarationName::CXXDestructorName:\r
- return Context.DeclarationNames.getCXXDestructorName(\r
- Context.getCanonicalType(readType(F, Record, Idx)));\r
-\r
- case DeclarationName::CXXConversionFunctionName:\r
- return Context.DeclarationNames.getCXXConversionFunctionName(\r
- Context.getCanonicalType(readType(F, Record, Idx)));\r
-\r
- case DeclarationName::CXXOperatorName:\r
- return Context.DeclarationNames.getCXXOperatorName(\r
- (OverloadedOperatorKind)Record[Idx++]);\r
-\r
- case DeclarationName::CXXLiteralOperatorName:\r
- return Context.DeclarationNames.getCXXLiteralOperatorName(\r
- GetIdentifierInfo(F, Record, Idx));\r
-\r
- case DeclarationName::CXXUsingDirective:\r
- return DeclarationName::getUsingDirectiveName();\r
- }\r
-\r
- llvm_unreachable("Invalid NameKind!");\r
-}\r
-\r
-void ASTReader::ReadDeclarationNameLoc(ModuleFile &F,\r
- DeclarationNameLoc &DNLoc,\r
- DeclarationName Name,\r
- const RecordData &Record, unsigned &Idx) {\r
- switch (Name.getNameKind()) {\r
- case DeclarationName::CXXConstructorName:\r
- case DeclarationName::CXXDestructorName:\r
- case DeclarationName::CXXConversionFunctionName:\r
- DNLoc.NamedType.TInfo = GetTypeSourceInfo(F, Record, Idx);\r
- break;\r
-\r
- case DeclarationName::CXXOperatorName:\r
- DNLoc.CXXOperatorName.BeginOpNameLoc\r
- = ReadSourceLocation(F, Record, Idx).getRawEncoding();\r
- DNLoc.CXXOperatorName.EndOpNameLoc\r
- = ReadSourceLocation(F, Record, Idx).getRawEncoding();\r
- break;\r
-\r
- case DeclarationName::CXXLiteralOperatorName:\r
- DNLoc.CXXLiteralOperatorName.OpNameLoc\r
- = ReadSourceLocation(F, Record, Idx).getRawEncoding();\r
- break;\r
-\r
- case DeclarationName::Identifier:\r
- case DeclarationName::ObjCZeroArgSelector:\r
- case DeclarationName::ObjCOneArgSelector:\r
- case DeclarationName::ObjCMultiArgSelector:\r
- case DeclarationName::CXXUsingDirective:\r
- break;\r
- }\r
-}\r
-\r
-void ASTReader::ReadDeclarationNameInfo(ModuleFile &F,\r
- DeclarationNameInfo &NameInfo,\r
- const RecordData &Record, unsigned &Idx) {\r
- NameInfo.setName(ReadDeclarationName(F, Record, Idx));\r
- NameInfo.setLoc(ReadSourceLocation(F, Record, Idx));\r
- DeclarationNameLoc DNLoc;\r
- ReadDeclarationNameLoc(F, DNLoc, NameInfo.getName(), Record, Idx);\r
- NameInfo.setInfo(DNLoc);\r
-}\r
-\r
-void ASTReader::ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info,\r
- const RecordData &Record, unsigned &Idx) {\r
- Info.QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx);\r
- unsigned NumTPLists = Record[Idx++];\r
- Info.NumTemplParamLists = NumTPLists;\r
- if (NumTPLists) {\r
- Info.TemplParamLists = new (Context) TemplateParameterList*[NumTPLists];\r
- for (unsigned i=0; i != NumTPLists; ++i)\r
- Info.TemplParamLists[i] = ReadTemplateParameterList(F, Record, Idx);\r
- }\r
-}\r
-\r
-TemplateName\r
-ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record, \r
- unsigned &Idx) {\r
- TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++];\r
- switch (Kind) {\r
- case TemplateName::Template:\r
- return TemplateName(ReadDeclAs<TemplateDecl>(F, Record, Idx));\r
-\r
- case TemplateName::OverloadedTemplate: {\r
- unsigned size = Record[Idx++];\r
- UnresolvedSet<8> Decls;\r
- while (size--)\r
- Decls.addDecl(ReadDeclAs<NamedDecl>(F, Record, Idx));\r
-\r
- return Context.getOverloadedTemplateName(Decls.begin(), Decls.end());\r
- }\r
-\r
- case TemplateName::QualifiedTemplate: {\r
- NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx);\r
- bool hasTemplKeyword = Record[Idx++];\r
- TemplateDecl *Template = ReadDeclAs<TemplateDecl>(F, Record, Idx);\r
- return Context.getQualifiedTemplateName(NNS, hasTemplKeyword, Template);\r
- }\r
-\r
- case TemplateName::DependentTemplate: {\r
- NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx);\r
- if (Record[Idx++]) // isIdentifier\r
- return Context.getDependentTemplateName(NNS,\r
- GetIdentifierInfo(F, Record, \r
- Idx));\r
- return Context.getDependentTemplateName(NNS,\r
- (OverloadedOperatorKind)Record[Idx++]);\r
- }\r
-\r
- case TemplateName::SubstTemplateTemplateParm: {\r
- TemplateTemplateParmDecl *param\r
- = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx);\r
- if (!param) return TemplateName();\r
- TemplateName replacement = ReadTemplateName(F, Record, Idx);\r
- return Context.getSubstTemplateTemplateParm(param, replacement);\r
- }\r
- \r
- case TemplateName::SubstTemplateTemplateParmPack: {\r
- TemplateTemplateParmDecl *Param \r
- = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx);\r
- if (!Param)\r
- return TemplateName();\r
- \r
- TemplateArgument ArgPack = ReadTemplateArgument(F, Record, Idx);\r
- if (ArgPack.getKind() != TemplateArgument::Pack)\r
- return TemplateName();\r
- \r
- return Context.getSubstTemplateTemplateParmPack(Param, ArgPack);\r
- }\r
- }\r
-\r
- llvm_unreachable("Unhandled template name kind!");\r
-}\r
-\r
-TemplateArgument\r
-ASTReader::ReadTemplateArgument(ModuleFile &F,\r
- const RecordData &Record, unsigned &Idx) {\r
- TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];\r
- switch (Kind) {\r
- case TemplateArgument::Null:\r
- return TemplateArgument();\r
- case TemplateArgument::Type:\r
- return TemplateArgument(readType(F, Record, Idx));\r
- case TemplateArgument::Declaration: {\r
- ValueDecl *D = ReadDeclAs<ValueDecl>(F, Record, Idx);\r
- bool ForReferenceParam = Record[Idx++];\r
- return TemplateArgument(D, ForReferenceParam);\r
- }\r
- case TemplateArgument::NullPtr:\r
- return TemplateArgument(readType(F, Record, Idx), /*isNullPtr*/true);\r
- case TemplateArgument::Integral: {\r
- llvm::APSInt Value = ReadAPSInt(Record, Idx);\r
- QualType T = readType(F, Record, Idx);\r
- return TemplateArgument(Context, Value, T);\r
- }\r
- case TemplateArgument::Template: \r
- return TemplateArgument(ReadTemplateName(F, Record, Idx));\r
- case TemplateArgument::TemplateExpansion: {\r
- TemplateName Name = ReadTemplateName(F, Record, Idx);\r
- llvm::Optional<unsigned> NumTemplateExpansions;\r
- if (unsigned NumExpansions = Record[Idx++])\r
- NumTemplateExpansions = NumExpansions - 1;\r
- return TemplateArgument(Name, NumTemplateExpansions);\r
- }\r
- case TemplateArgument::Expression:\r
- return TemplateArgument(ReadExpr(F));\r
- case TemplateArgument::Pack: {\r
- unsigned NumArgs = Record[Idx++];\r
- TemplateArgument *Args = new (Context) TemplateArgument[NumArgs];\r
- for (unsigned I = 0; I != NumArgs; ++I)\r
- Args[I] = ReadTemplateArgument(F, Record, Idx);\r
- return TemplateArgument(Args, NumArgs);\r
- }\r
- }\r
-\r
- llvm_unreachable("Unhandled template argument kind!");\r
-}\r
-\r
-TemplateParameterList *\r
-ASTReader::ReadTemplateParameterList(ModuleFile &F,\r
- const RecordData &Record, unsigned &Idx) {\r
- SourceLocation TemplateLoc = ReadSourceLocation(F, Record, Idx);\r
- SourceLocation LAngleLoc = ReadSourceLocation(F, Record, Idx);\r
- SourceLocation RAngleLoc = ReadSourceLocation(F, Record, Idx);\r
-\r
- unsigned NumParams = Record[Idx++];\r
- SmallVector<NamedDecl *, 16> Params;\r
- Params.reserve(NumParams);\r
- while (NumParams--)\r
- Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx));\r
-\r
- TemplateParameterList* TemplateParams =\r
- TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,\r
- Params.data(), Params.size(), RAngleLoc);\r
- return TemplateParams;\r
-}\r
-\r
-void\r
-ASTReader::\r
-ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs,\r
- ModuleFile &F, const RecordData &Record,\r
- unsigned &Idx) {\r
- unsigned NumTemplateArgs = Record[Idx++];\r
- TemplArgs.reserve(NumTemplateArgs);\r
- while (NumTemplateArgs--)\r
- TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx));\r
-}\r
-\r
-/// \brief Read a UnresolvedSet structure.\r
-void ASTReader::ReadUnresolvedSet(ModuleFile &F, ASTUnresolvedSet &Set,\r
- const RecordData &Record, unsigned &Idx) {\r
- unsigned NumDecls = Record[Idx++];\r
- Set.reserve(Context, NumDecls);\r
- while (NumDecls--) {\r
- NamedDecl *D = ReadDeclAs<NamedDecl>(F, Record, Idx);\r
- AccessSpecifier AS = (AccessSpecifier)Record[Idx++];\r
- Set.addDecl(Context, D, AS);\r
- }\r
-}\r
-\r
-CXXBaseSpecifier\r
-ASTReader::ReadCXXBaseSpecifier(ModuleFile &F,\r
- const RecordData &Record, unsigned &Idx) {\r
- bool isVirtual = static_cast<bool>(Record[Idx++]);\r
- bool isBaseOfClass = static_cast<bool>(Record[Idx++]);\r
- AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]);\r
- bool inheritConstructors = static_cast<bool>(Record[Idx++]);\r
- TypeSourceInfo *TInfo = GetTypeSourceInfo(F, Record, Idx);\r
- SourceRange Range = ReadSourceRange(F, Record, Idx);\r
- SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Idx);\r
- CXXBaseSpecifier Result(Range, isVirtual, isBaseOfClass, AS, TInfo, \r
- EllipsisLoc);\r
- Result.setInheritConstructors(inheritConstructors);\r
- return Result;\r
-}\r
-\r
-std::pair<CXXCtorInitializer **, unsigned>\r
-ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,\r
- unsigned &Idx) {\r
- CXXCtorInitializer **CtorInitializers = 0;\r
- unsigned NumInitializers = Record[Idx++];\r
- if (NumInitializers) {\r
- CtorInitializers\r
- = new (Context) CXXCtorInitializer*[NumInitializers];\r
- for (unsigned i=0; i != NumInitializers; ++i) {\r
- TypeSourceInfo *TInfo = 0;\r
- bool IsBaseVirtual = false;\r
- FieldDecl *Member = 0;\r
- IndirectFieldDecl *IndirectMember = 0;\r
-\r
- CtorInitializerType Type = (CtorInitializerType)Record[Idx++];\r
- switch (Type) {\r
- case CTOR_INITIALIZER_BASE:\r
- TInfo = GetTypeSourceInfo(F, Record, Idx);\r
- IsBaseVirtual = Record[Idx++];\r
- break;\r
- \r
- case CTOR_INITIALIZER_DELEGATING:\r
- TInfo = GetTypeSourceInfo(F, Record, Idx);\r
- break;\r
-\r
- case CTOR_INITIALIZER_MEMBER:\r
- Member = ReadDeclAs<FieldDecl>(F, Record, Idx);\r
- break;\r
-\r
- case CTOR_INITIALIZER_INDIRECT_MEMBER:\r
- IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx);\r
- break;\r
- }\r
-\r
- SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx);\r
- Expr *Init = ReadExpr(F);\r
- SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);\r
- SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);\r
- bool IsWritten = Record[Idx++];\r
- unsigned SourceOrderOrNumArrayIndices;\r
- SmallVector<VarDecl *, 8> Indices;\r
- if (IsWritten) {\r
- SourceOrderOrNumArrayIndices = Record[Idx++];\r
- } else {\r
- SourceOrderOrNumArrayIndices = Record[Idx++];\r
- Indices.reserve(SourceOrderOrNumArrayIndices);\r
- for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)\r
- Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx));\r
- }\r
-\r
- CXXCtorInitializer *BOMInit;\r
- if (Type == CTOR_INITIALIZER_BASE) {\r
- BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual,\r
- LParenLoc, Init, RParenLoc,\r
- MemberOrEllipsisLoc);\r
- } else if (Type == CTOR_INITIALIZER_DELEGATING) {\r
- BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc,\r
- Init, RParenLoc);\r
- } else if (IsWritten) {\r
- if (Member)\r
- BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc,\r
- LParenLoc, Init, RParenLoc);\r
- else \r
- BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember,\r
- MemberOrEllipsisLoc, LParenLoc,\r
- Init, RParenLoc);\r
- } else {\r
- BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc,\r
- LParenLoc, Init, RParenLoc,\r
- Indices.data(), Indices.size());\r
- }\r
-\r
- if (IsWritten)\r
- BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);\r
- CtorInitializers[i] = BOMInit;\r
- }\r
- }\r
-\r
- return std::make_pair(CtorInitializers, NumInitializers);\r
-}\r
-\r
-NestedNameSpecifier *\r
-ASTReader::ReadNestedNameSpecifier(ModuleFile &F,\r
- const RecordData &Record, unsigned &Idx) {\r
- unsigned N = Record[Idx++];\r
- NestedNameSpecifier *NNS = 0, *Prev = 0;\r
- for (unsigned I = 0; I != N; ++I) {\r
- NestedNameSpecifier::SpecifierKind Kind\r
- = (NestedNameSpecifier::SpecifierKind)Record[Idx++];\r
- switch (Kind) {\r
- case NestedNameSpecifier::Identifier: {\r
- IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx);\r
- NNS = NestedNameSpecifier::Create(Context, Prev, II);\r
- break;\r
- }\r
-\r
- case NestedNameSpecifier::Namespace: {\r
- NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx);\r
- NNS = NestedNameSpecifier::Create(Context, Prev, NS);\r
- break;\r
- }\r
-\r
- case NestedNameSpecifier::NamespaceAlias: {\r
- NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx);\r
- NNS = NestedNameSpecifier::Create(Context, Prev, Alias);\r
- break;\r
- }\r
-\r
- case NestedNameSpecifier::TypeSpec:\r
- case NestedNameSpecifier::TypeSpecWithTemplate: {\r
- const Type *T = readType(F, Record, Idx).getTypePtrOrNull();\r
- if (!T)\r
- return 0;\r
- \r
- bool Template = Record[Idx++];\r
- NNS = NestedNameSpecifier::Create(Context, Prev, Template, T);\r
- break;\r
- }\r
-\r
- case NestedNameSpecifier::Global: {\r
- NNS = NestedNameSpecifier::GlobalSpecifier(Context);\r
- // No associated value, and there can't be a prefix.\r
- break;\r
- }\r
- }\r
- Prev = NNS;\r
- }\r
- return NNS;\r
-}\r
-\r
-NestedNameSpecifierLoc\r
-ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record, \r
- unsigned &Idx) {\r
- unsigned N = Record[Idx++];\r
- NestedNameSpecifierLocBuilder Builder;\r
- for (unsigned I = 0; I != N; ++I) {\r
- NestedNameSpecifier::SpecifierKind Kind\r
- = (NestedNameSpecifier::SpecifierKind)Record[Idx++];\r
- switch (Kind) {\r
- case NestedNameSpecifier::Identifier: {\r
- IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx); \r
- SourceRange Range = ReadSourceRange(F, Record, Idx);\r
- Builder.Extend(Context, II, Range.getBegin(), Range.getEnd());\r
- break;\r
- }\r
-\r
- case NestedNameSpecifier::Namespace: {\r
- NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx);\r
- SourceRange Range = ReadSourceRange(F, Record, Idx);\r
- Builder.Extend(Context, NS, Range.getBegin(), Range.getEnd());\r
- break;\r
- }\r
-\r
- case NestedNameSpecifier::NamespaceAlias: {\r
- NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx);\r
- SourceRange Range = ReadSourceRange(F, Record, Idx);\r
- Builder.Extend(Context, Alias, Range.getBegin(), Range.getEnd());\r
- break;\r
- }\r
-\r
- case NestedNameSpecifier::TypeSpec:\r
- case NestedNameSpecifier::TypeSpecWithTemplate: {\r
- bool Template = Record[Idx++];\r
- TypeSourceInfo *T = GetTypeSourceInfo(F, Record, Idx);\r
- if (!T)\r
- return NestedNameSpecifierLoc();\r
- SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);\r
-\r
- // FIXME: 'template' keyword location not saved anywhere, so we fake it.\r
- Builder.Extend(Context, \r
- Template? T->getTypeLoc().getBeginLoc() : SourceLocation(),\r
- T->getTypeLoc(), ColonColonLoc);\r
- break;\r
- }\r
-\r
- case NestedNameSpecifier::Global: {\r
- SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);\r
- Builder.MakeGlobal(Context, ColonColonLoc);\r
- break;\r
- }\r
- }\r
- }\r
- \r
- return Builder.getWithLocInContext(Context);\r
-}\r
-\r
-SourceRange\r
-ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record,\r
- unsigned &Idx) {\r
- SourceLocation beg = ReadSourceLocation(F, Record, Idx);\r
- SourceLocation end = ReadSourceLocation(F, Record, Idx);\r
- return SourceRange(beg, end);\r
-}\r
-\r
-/// \brief Read an integral value\r
-llvm::APInt ASTReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {\r
- unsigned BitWidth = Record[Idx++];\r
- unsigned NumWords = llvm::APInt::getNumWords(BitWidth);\r
- llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);\r
- Idx += NumWords;\r
- return Result;\r
-}\r
-\r
-/// \brief Read a signed integral value\r
-llvm::APSInt ASTReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {\r
- bool isUnsigned = Record[Idx++];\r
- return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);\r
-}\r
-\r
-/// \brief Read a floating-point value\r
-llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {\r
- return llvm::APFloat(ReadAPInt(Record, Idx));\r
-}\r
-\r
-// \brief Read a string\r
-std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) {\r
- unsigned Len = Record[Idx++];\r
- std::string Result(Record.data() + Idx, Record.data() + Idx + Len);\r
- Idx += Len;\r
- return Result;\r
-}\r
-\r
-VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record, \r
- unsigned &Idx) {\r
- unsigned Major = Record[Idx++];\r
- unsigned Minor = Record[Idx++];\r
- unsigned Subminor = Record[Idx++];\r
- if (Minor == 0)\r
- return VersionTuple(Major);\r
- if (Subminor == 0)\r
- return VersionTuple(Major, Minor - 1);\r
- return VersionTuple(Major, Minor - 1, Subminor - 1);\r
-}\r
-\r
-CXXTemporary *ASTReader::ReadCXXTemporary(ModuleFile &F, \r
- const RecordData &Record,\r
- unsigned &Idx) {\r
- CXXDestructorDecl *Decl = ReadDeclAs<CXXDestructorDecl>(F, Record, Idx);\r
- return CXXTemporary::Create(Context, Decl);\r
-}\r
-\r
-DiagnosticBuilder ASTReader::Diag(unsigned DiagID) {\r
- return Diag(SourceLocation(), DiagID);\r
-}\r
-\r
-DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) {\r
- return Diags.Report(Loc, DiagID);\r
-}\r
-\r
-/// \brief Retrieve the identifier table associated with the\r
-/// preprocessor.\r
-IdentifierTable &ASTReader::getIdentifierTable() {\r
- return PP.getIdentifierTable();\r
-}\r
-\r
-/// \brief Record that the given ID maps to the given switch-case\r
-/// statement.\r
-void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {\r
- assert((*CurrSwitchCaseStmts)[ID] == 0 &&\r
- "Already have a SwitchCase with this ID");\r
- (*CurrSwitchCaseStmts)[ID] = SC;\r
-}\r
-\r
-/// \brief Retrieve the switch-case statement with the given ID.\r
-SwitchCase *ASTReader::getSwitchCaseWithID(unsigned ID) {\r
- assert((*CurrSwitchCaseStmts)[ID] != 0 && "No SwitchCase with this ID");\r
- return (*CurrSwitchCaseStmts)[ID];\r
-}\r
-\r
-void ASTReader::ClearSwitchCaseIDs() {\r
- CurrSwitchCaseStmts->clear();\r
-}\r
-\r
-void ASTReader::ReadComments() {\r
- std::vector<RawComment *> Comments;\r
- for (SmallVectorImpl<std::pair<llvm::BitstreamCursor,\r
- serialization::ModuleFile *> >::iterator\r
- I = CommentsCursors.begin(),\r
- E = CommentsCursors.end();\r
- I != E; ++I) {\r
- llvm::BitstreamCursor &Cursor = I->first;\r
- serialization::ModuleFile &F = *I->second;\r
- SavedStreamPosition SavedPosition(Cursor);\r
-\r
- RecordData Record;\r
- while (true) {\r
- unsigned Code = Cursor.ReadCode();\r
- if (Code == llvm::bitc::END_BLOCK)\r
- break;\r
-\r
- if (Code == llvm::bitc::ENTER_SUBBLOCK) {\r
- // No known subblocks, always skip them.\r
- Cursor.ReadSubBlockID();\r
- if (Cursor.SkipBlock()) {\r
- Error("malformed block record in AST file");\r
- return;\r
- }\r
- continue;\r
- }\r
-\r
- if (Code == llvm::bitc::DEFINE_ABBREV) {\r
- Cursor.ReadAbbrevRecord();\r
- continue;\r
- }\r
-\r
- // Read a record.\r
- Record.clear();\r
- switch ((CommentRecordTypes) Cursor.ReadRecord(Code, Record)) {\r
- case COMMENTS_RAW_COMMENT: {\r
- unsigned Idx = 0;\r
- SourceRange SR = ReadSourceRange(F, Record, Idx);\r
- RawComment::CommentKind Kind =\r
- (RawComment::CommentKind) Record[Idx++];\r
- bool IsTrailingComment = Record[Idx++];\r
- bool IsAlmostTrailingComment = Record[Idx++];\r
- Comments.push_back(new (Context) RawComment(SR, Kind,\r
- IsTrailingComment,\r
- IsAlmostTrailingComment));\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- Context.Comments.addCommentsToFront(Comments);\r
-}\r
-\r
-void ASTReader::finishPendingActions() {\r
- while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() ||\r
- !PendingMacroIDs.empty()) {\r
- // If any identifiers with corresponding top-level declarations have\r
- // been loaded, load those declarations now.\r
- while (!PendingIdentifierInfos.empty()) {\r
- SetGloballyVisibleDecls(PendingIdentifierInfos.front().II,\r
- PendingIdentifierInfos.front().DeclIDs, true);\r
- PendingIdentifierInfos.pop_front();\r
- }\r
- \r
- // Load pending declaration chains.\r
- for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {\r
- loadPendingDeclChain(PendingDeclChains[I]);\r
- PendingDeclChainsKnown.erase(PendingDeclChains[I]);\r
- }\r
- PendingDeclChains.clear();\r
-\r
- // Load any pending macro definitions.\r
- for (unsigned I = 0; I != PendingMacroIDs.size(); ++I) {\r
- // FIXME: std::move here\r
- SmallVector<MacroID, 2> GlobalIDs = PendingMacroIDs.begin()[I].second;\r
- MacroInfo *Hint = 0;\r
- for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;\r
- ++IDIdx) {\r
- Hint = getMacro(GlobalIDs[IDIdx], Hint);\r
- }\r
- }\r
- PendingMacroIDs.clear();\r
- }\r
- \r
- // If we deserialized any C++ or Objective-C class definitions, any\r
- // Objective-C protocol definitions, or any redeclarable templates, make sure\r
- // that all redeclarations point to the definitions. Note that this can only \r
- // happen now, after the redeclaration chains have been fully wired.\r
- for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),\r
- DEnd = PendingDefinitions.end();\r
- D != DEnd; ++D) {\r
- if (TagDecl *TD = dyn_cast<TagDecl>(*D)) {\r
- if (const TagType *TagT = dyn_cast<TagType>(TD->TypeForDecl)) {\r
- // Make sure that the TagType points at the definition.\r
- const_cast<TagType*>(TagT)->decl = TD;\r
- }\r
- \r
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) {\r
- for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(),\r
- REnd = RD->redecls_end();\r
- R != REnd; ++R)\r
- cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData;\r
- \r
- }\r
-\r
- continue;\r
- }\r
- \r
- if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) {\r
- // Make sure that the ObjCInterfaceType points at the definition.\r
- const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl))\r
- ->Decl = ID;\r
- \r
- for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(),\r
- REnd = ID->redecls_end();\r
- R != REnd; ++R)\r
- R->Data = ID->Data;\r
- \r
- continue;\r
- }\r
- \r
- if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) {\r
- for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(),\r
- REnd = PD->redecls_end();\r
- R != REnd; ++R)\r
- R->Data = PD->Data;\r
- \r
- continue;\r
- }\r
- \r
- RedeclarableTemplateDecl *RTD\r
- = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl();\r
- for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(),\r
- REnd = RTD->redecls_end();\r
- R != REnd; ++R)\r
- R->Common = RTD->Common;\r
- }\r
- PendingDefinitions.clear();\r
-\r
- // Load the bodies of any functions or methods we've encountered. We do\r
- // this now (delayed) so that we can be sure that the declaration chains\r
- // have been fully wired up.\r
- for (PendingBodiesMap::iterator PB = PendingBodies.begin(),\r
- PBEnd = PendingBodies.end();\r
- PB != PBEnd; ++PB) {\r
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PB->first)) {\r
- // FIXME: Check for =delete/=default?\r
- // FIXME: Complain about ODR violations here?\r
- if (!getContext().getLangOpts().Modules || !FD->hasBody())\r
- FD->setLazyBody(PB->second);\r
- continue;\r
- }\r
-\r
- ObjCMethodDecl *MD = cast<ObjCMethodDecl>(PB->first);\r
- if (!getContext().getLangOpts().Modules || !MD->hasBody())\r
- MD->setLazyBody(PB->second);\r
- }\r
- PendingBodies.clear();\r
-}\r
-\r
-void ASTReader::FinishedDeserializing() {\r
- assert(NumCurrentElementsDeserializing &&\r
- "FinishedDeserializing not paired with StartedDeserializing");\r
- if (NumCurrentElementsDeserializing == 1) {\r
- // We decrease NumCurrentElementsDeserializing only after pending actions\r
- // are finished, to avoid recursively re-calling finishPendingActions().\r
- finishPendingActions();\r
- }\r
- --NumCurrentElementsDeserializing;\r
-\r
- if (NumCurrentElementsDeserializing == 0 &&\r
- Consumer && !PassingDeclsToConsumer) {\r
- // Guard variable to avoid recursively redoing the process of passing\r
- // decls to consumer.\r
- SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer,\r
- true);\r
-\r
- while (!InterestingDecls.empty()) {\r
- // We are not in recursive loading, so it's safe to pass the "interesting"\r
- // decls to the consumer.\r
- Decl *D = InterestingDecls.front();\r
- InterestingDecls.pop_front();\r
- PassInterestingDeclToConsumer(D);\r
- }\r
- }\r
-}\r
-\r
-ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,\r
- StringRef isysroot, bool DisableValidation,\r
- bool AllowASTWithCompilerErrors)\r
- : Listener(new PCHValidator(PP, *this)), DeserializationListener(0),\r
- SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),\r
- Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context),\r
- Consumer(0), ModuleMgr(PP.getFileManager()),\r
- isysroot(isysroot), DisableValidation(DisableValidation),\r
- AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), \r
- CurrentGeneration(0), CurrSwitchCaseStmts(&SwitchCaseStmts),\r
- NumSLocEntriesRead(0), TotalNumSLocEntries(0), \r
- NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), \r
- TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), \r
- NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0), \r
- NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), \r
- NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),\r
- TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0),\r
- PassingDeclsToConsumer(false),\r
- NumCXXBaseSpecifiersLoaded(0)\r
-{\r
- SourceMgr.setExternalSLocEntrySource(this);\r
-}\r
-\r
-ASTReader::~ASTReader() {\r
- for (DeclContextVisibleUpdatesPending::iterator\r
- I = PendingVisibleUpdates.begin(),\r
- E = PendingVisibleUpdates.end();\r
- I != E; ++I) {\r
- for (DeclContextVisibleUpdates::iterator J = I->second.begin(),\r
- F = I->second.end();\r
- J != F; ++J)\r
- delete J->first;\r
- }\r
-}\r
+//===--- ASTReader.cpp - AST File Reader ------------------------*- 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 ASTReader class, which reads AST files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Serialization/ASTReader.h"
+#include "ASTCommon.h"
+#include "ASTReaderInternals.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemStatCache.h"
+#include "clang/Basic/OnDiskHashTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceManagerInternals.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/Version.h"
+#include "clang/Basic/VersionTuple.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+#include "clang/Serialization/ModuleManager.h"
+#include "clang/Serialization/SerializationDiagnostic.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/system_error.h"
+#include <algorithm>
+#include <cstdio>
+#include <iterator>
+
+using namespace clang;
+using namespace clang::serialization;
+using namespace clang::serialization::reader;
+
+//===----------------------------------------------------------------------===//
+// PCH validator implementation
+//===----------------------------------------------------------------------===//
+
+ASTReaderListener::~ASTReaderListener() {}
+
+/// \brief Compare the given set of language options against an existing set of
+/// language options.
+///
+/// \param Diags If non-NULL, diagnostics will be emitted via this engine.
+///
+/// \returns true if the languagae options mis-match, false otherwise.
+static bool checkLanguageOptions(const LangOptions &LangOpts,
+ const LangOptions &ExistingLangOpts,
+ DiagnosticsEngine *Diags) {
+#define LANGOPT(Name, Bits, Default, Description) \
+ if (ExistingLangOpts.Name != LangOpts.Name) { \
+ if (Diags) \
+ Diags->Report(diag::err_pch_langopt_mismatch) \
+ << Description << LangOpts.Name << ExistingLangOpts.Name; \
+ return true; \
+ }
+
+#define VALUE_LANGOPT(Name, Bits, Default, Description) \
+ if (ExistingLangOpts.Name != LangOpts.Name) { \
+ if (Diags) \
+ Diags->Report(diag::err_pch_langopt_value_mismatch) \
+ << Description; \
+ return true; \
+ }
+
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+ if (ExistingLangOpts.get##Name() != LangOpts.get##Name()) { \
+ if (Diags) \
+ Diags->Report(diag::err_pch_langopt_value_mismatch) \
+ << Description; \
+ return true; \
+ }
+
+#define BENIGN_LANGOPT(Name, Bits, Default, Description)
+#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
+#include "clang/Basic/LangOptions.def"
+
+ if (ExistingLangOpts.ObjCRuntime != LangOpts.ObjCRuntime) {
+ if (Diags)
+ Diags->Report(diag::err_pch_langopt_value_mismatch)
+ << "target Objective-C runtime";
+ return true;
+ }
+
+ return false;
+}
+
+/// \brief Compare the given set of target options against an existing set of
+/// target options.
+///
+/// \param Diags If non-NULL, diagnostics will be emitted via this engine.
+///
+/// \returns true if the target options mis-match, false otherwise.
+static bool checkTargetOptions(const TargetOptions &TargetOpts,
+ const TargetOptions &ExistingTargetOpts,
+ DiagnosticsEngine *Diags) {
+#define CHECK_TARGET_OPT(Field, Name) \
+ if (TargetOpts.Field != ExistingTargetOpts.Field) { \
+ if (Diags) \
+ Diags->Report(diag::err_pch_targetopt_mismatch) \
+ << Name << TargetOpts.Field << ExistingTargetOpts.Field; \
+ return true; \
+ }
+
+ CHECK_TARGET_OPT(Triple, "target");
+ CHECK_TARGET_OPT(CPU, "target CPU");
+ CHECK_TARGET_OPT(ABI, "target ABI");
+ CHECK_TARGET_OPT(CXXABI, "target C++ ABI");
+ CHECK_TARGET_OPT(LinkerVersion, "target linker version");
+#undef CHECK_TARGET_OPT
+
+ // Compare feature sets.
+ SmallVector<StringRef, 4> ExistingFeatures(
+ ExistingTargetOpts.FeaturesAsWritten.begin(),
+ ExistingTargetOpts.FeaturesAsWritten.end());
+ SmallVector<StringRef, 4> ReadFeatures(TargetOpts.FeaturesAsWritten.begin(),
+ TargetOpts.FeaturesAsWritten.end());
+ std::sort(ExistingFeatures.begin(), ExistingFeatures.end());
+ std::sort(ReadFeatures.begin(), ReadFeatures.end());
+
+ unsigned ExistingIdx = 0, ExistingN = ExistingFeatures.size();
+ unsigned ReadIdx = 0, ReadN = ReadFeatures.size();
+ while (ExistingIdx < ExistingN && ReadIdx < ReadN) {
+ if (ExistingFeatures[ExistingIdx] == ReadFeatures[ReadIdx]) {
+ ++ExistingIdx;
+ ++ReadIdx;
+ continue;
+ }
+
+ if (ReadFeatures[ReadIdx] < ExistingFeatures[ExistingIdx]) {
+ if (Diags)
+ Diags->Report(diag::err_pch_targetopt_feature_mismatch)
+ << false << ReadFeatures[ReadIdx];
+ return true;
+ }
+
+ if (Diags)
+ Diags->Report(diag::err_pch_targetopt_feature_mismatch)
+ << true << ExistingFeatures[ExistingIdx];
+ return true;
+ }
+
+ if (ExistingIdx < ExistingN) {
+ if (Diags)
+ Diags->Report(diag::err_pch_targetopt_feature_mismatch)
+ << true << ExistingFeatures[ExistingIdx];
+ return true;
+ }
+
+ if (ReadIdx < ReadN) {
+ if (Diags)
+ Diags->Report(diag::err_pch_targetopt_feature_mismatch)
+ << false << ReadFeatures[ReadIdx];
+ return true;
+ }
+
+ return false;
+}
+
+bool
+PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts,
+ bool Complain) {
+ const LangOptions &ExistingLangOpts = PP.getLangOpts();
+ return checkLanguageOptions(LangOpts, ExistingLangOpts,
+ Complain? &Reader.Diags : 0);
+}
+
+bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
+ bool Complain) {
+ const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts();
+ return checkTargetOptions(TargetOpts, ExistingTargetOpts,
+ Complain? &Reader.Diags : 0);
+}
+
+namespace {
+ typedef llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >
+ MacroDefinitionsMap;
+}
+
+/// \brief Collect the macro definitions provided by the given preprocessor
+/// options.
+static void collectMacroDefinitions(const PreprocessorOptions &PPOpts,
+ MacroDefinitionsMap &Macros,
+ SmallVectorImpl<StringRef> *MacroNames = 0){
+ for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) {
+ StringRef Macro = PPOpts.Macros[I].first;
+ bool IsUndef = PPOpts.Macros[I].second;
+
+ std::pair<StringRef, StringRef> MacroPair = Macro.split('=');
+ StringRef MacroName = MacroPair.first;
+ StringRef MacroBody = MacroPair.second;
+
+ // For an #undef'd macro, we only care about the name.
+ if (IsUndef) {
+ if (MacroNames && !Macros.count(MacroName))
+ MacroNames->push_back(MacroName);
+
+ Macros[MacroName] = std::make_pair("", true);
+ continue;
+ }
+
+ // For a #define'd macro, figure out the actual definition.
+ if (MacroName.size() == Macro.size())
+ MacroBody = "1";
+ else {
+ // Note: GCC drops anything following an end-of-line character.
+ StringRef::size_type End = MacroBody.find_first_of("\n\r");
+ MacroBody = MacroBody.substr(0, End);
+ }
+
+ if (MacroNames && !Macros.count(MacroName))
+ MacroNames->push_back(MacroName);
+ Macros[MacroName] = std::make_pair(MacroBody, false);
+ }
+}
+
+/// \brief Check the preprocessor options deserialized from the control block
+/// against the preprocessor options in an existing preprocessor.
+///
+/// \param Diags If non-null, produce diagnostics for any mismatches incurred.
+static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
+ const PreprocessorOptions &ExistingPPOpts,
+ DiagnosticsEngine *Diags,
+ FileManager &FileMgr,
+ std::string &SuggestedPredefines) {
+ // Check macro definitions.
+ MacroDefinitionsMap ASTFileMacros;
+ collectMacroDefinitions(PPOpts, ASTFileMacros);
+ MacroDefinitionsMap ExistingMacros;
+ SmallVector<StringRef, 4> ExistingMacroNames;
+ collectMacroDefinitions(ExistingPPOpts, ExistingMacros, &ExistingMacroNames);
+
+ for (unsigned I = 0, N = ExistingMacroNames.size(); I != N; ++I) {
+ // Dig out the macro definition in the existing preprocessor options.
+ StringRef MacroName = ExistingMacroNames[I];
+ std::pair<StringRef, bool> Existing = ExistingMacros[MacroName];
+
+ // Check whether we know anything about this macro name or not.
+ llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >::iterator Known
+ = ASTFileMacros.find(MacroName);
+ if (Known == ASTFileMacros.end()) {
+ // FIXME: Check whether this identifier was referenced anywhere in the
+ // AST file. If so, we should reject the AST file. Unfortunately, this
+ // information isn't in the control block. What shall we do about it?
+
+ if (Existing.second) {
+ SuggestedPredefines += "#undef ";
+ SuggestedPredefines += MacroName.str();
+ SuggestedPredefines += '\n';
+ } else {
+ SuggestedPredefines += "#define ";
+ SuggestedPredefines += MacroName.str();
+ SuggestedPredefines += ' ';
+ SuggestedPredefines += Existing.first.str();
+ SuggestedPredefines += '\n';
+ }
+ continue;
+ }
+
+ // If the macro was defined in one but undef'd in the other, we have a
+ // conflict.
+ if (Existing.second != Known->second.second) {
+ if (Diags) {
+ Diags->Report(diag::err_pch_macro_def_undef)
+ << MacroName << Known->second.second;
+ }
+ return true;
+ }
+
+ // If the macro was #undef'd in both, or if the macro bodies are identical,
+ // it's fine.
+ if (Existing.second || Existing.first == Known->second.first)
+ continue;
+
+ // The macro bodies differ; complain.
+ if (Diags) {
+ Diags->Report(diag::err_pch_macro_def_conflict)
+ << MacroName << Known->second.first << Existing.first;
+ }
+ return true;
+ }
+
+ // Check whether we're using predefines.
+ if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines) {
+ if (Diags) {
+ Diags->Report(diag::err_pch_undef) << ExistingPPOpts.UsePredefines;
+ }
+ return true;
+ }
+
+ // Compute the #include and #include_macros lines we need.
+ for (unsigned I = 0, N = ExistingPPOpts.Includes.size(); I != N; ++I) {
+ StringRef File = ExistingPPOpts.Includes[I];
+ if (File == ExistingPPOpts.ImplicitPCHInclude)
+ continue;
+
+ if (std::find(PPOpts.Includes.begin(), PPOpts.Includes.end(), File)
+ != PPOpts.Includes.end())
+ continue;
+
+ SuggestedPredefines += "#include \"";
+ SuggestedPredefines +=
+ HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+ SuggestedPredefines += "\"\n";
+ }
+
+ for (unsigned I = 0, N = ExistingPPOpts.MacroIncludes.size(); I != N; ++I) {
+ StringRef File = ExistingPPOpts.MacroIncludes[I];
+ if (std::find(PPOpts.MacroIncludes.begin(), PPOpts.MacroIncludes.end(),
+ File)
+ != PPOpts.MacroIncludes.end())
+ continue;
+
+ SuggestedPredefines += "#__include_macros \"";
+ SuggestedPredefines +=
+ HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+ SuggestedPredefines += "\"\n##\n";
+ }
+
+ return false;
+}
+
+bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
+ bool Complain,
+ std::string &SuggestedPredefines) {
+ const PreprocessorOptions &ExistingPPOpts = PP.getPreprocessorOpts();
+
+ return checkPreprocessorOptions(PPOpts, ExistingPPOpts,
+ Complain? &Reader.Diags : 0,
+ PP.getFileManager(),
+ SuggestedPredefines);
+}
+
+void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI,
+ unsigned ID) {
+ PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID);
+ ++NumHeaderInfos;
+}
+
+void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) {
+ PP.setCounterValue(Value);
+}
+
+//===----------------------------------------------------------------------===//
+// AST reader implementation
+//===----------------------------------------------------------------------===//
+
+void
+ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) {
+ DeserializationListener = Listener;
+}
+
+
+
+unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) {
+ return serialization::ComputeHash(Sel);
+}
+
+
+std::pair<unsigned, unsigned>
+ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
+ using namespace clang::io;
+ unsigned KeyLen = ReadUnalignedLE16(d);
+ unsigned DataLen = ReadUnalignedLE16(d);
+ return std::make_pair(KeyLen, DataLen);
+}
+
+ASTSelectorLookupTrait::internal_key_type
+ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {
+ using namespace clang::io;
+ SelectorTable &SelTable = Reader.getContext().Selectors;
+ unsigned N = ReadUnalignedLE16(d);
+ IdentifierInfo *FirstII
+ = Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
+ if (N == 0)
+ return SelTable.getNullarySelector(FirstII);
+ else if (N == 1)
+ return SelTable.getUnarySelector(FirstII);
+
+ SmallVector<IdentifierInfo *, 16> Args;
+ Args.push_back(FirstII);
+ for (unsigned I = 1; I != N; ++I)
+ Args.push_back(Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)));
+
+ return SelTable.getSelector(N, Args.data());
+}
+
+ASTSelectorLookupTrait::data_type
+ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d,
+ unsigned DataLen) {
+ using namespace clang::io;
+
+ data_type Result;
+
+ Result.ID = Reader.getGlobalSelectorID(F, ReadUnalignedLE32(d));
+ unsigned NumInstanceMethods = ReadUnalignedLE16(d);
+ unsigned NumFactoryMethods = ReadUnalignedLE16(d);
+
+ // Load instance methods
+ for (unsigned I = 0; I != NumInstanceMethods; ++I) {
+ if (ObjCMethodDecl *Method
+ = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
+ Result.Instance.push_back(Method);
+ }
+
+ // Load factory methods
+ for (unsigned I = 0; I != NumFactoryMethods; ++I) {
+ if (ObjCMethodDecl *Method
+ = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
+ Result.Factory.push_back(Method);
+ }
+
+ return Result;
+}
+
+unsigned ASTIdentifierLookupTrait::ComputeHash(const internal_key_type& a) {
+ return llvm::HashString(StringRef(a.first, a.second));
+}
+
+std::pair<unsigned, unsigned>
+ASTIdentifierLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
+ using namespace clang::io;
+ unsigned DataLen = ReadUnalignedLE16(d);
+ unsigned KeyLen = ReadUnalignedLE16(d);
+ return std::make_pair(KeyLen, DataLen);
+}
+
+std::pair<const char*, unsigned>
+ASTIdentifierLookupTrait::ReadKey(const unsigned char* d, unsigned n) {
+ assert(n >= 2 && d[n-1] == '\0');
+ return std::make_pair((const char*) d, n-1);
+}
+
+IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
+ const unsigned char* d,
+ unsigned DataLen) {
+ using namespace clang::io;
+ unsigned RawID = ReadUnalignedLE32(d);
+ bool IsInteresting = RawID & 0x01;
+
+ // Wipe out the "is interesting" bit.
+ RawID = RawID >> 1;
+
+ IdentID ID = Reader.getGlobalIdentifierID(F, RawID);
+ if (!IsInteresting) {
+ // For uninteresting identifiers, just build the IdentifierInfo
+ // and associate it with the persistent ID.
+ IdentifierInfo *II = KnownII;
+ if (!II) {
+ II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
+ KnownII = II;
+ }
+ Reader.SetIdentifierInfo(ID, II);
+ II->setIsFromAST();
+ Reader.markIdentifierUpToDate(II);
+ return II;
+ }
+
+ unsigned ObjCOrBuiltinID = ReadUnalignedLE16(d);
+ unsigned Bits = ReadUnalignedLE16(d);
+ bool CPlusPlusOperatorKeyword = Bits & 0x01;
+ Bits >>= 1;
+ bool HasRevertedTokenIDToIdentifier = Bits & 0x01;
+ Bits >>= 1;
+ bool Poisoned = Bits & 0x01;
+ Bits >>= 1;
+ bool ExtensionToken = Bits & 0x01;
+ Bits >>= 1;
+ bool hadMacroDefinition = Bits & 0x01;
+ Bits >>= 1;
+
+ assert(Bits == 0 && "Extra bits in the identifier?");
+ DataLen -= 8;
+
+ // Build the IdentifierInfo itself and link the identifier ID with
+ // the new IdentifierInfo.
+ IdentifierInfo *II = KnownII;
+ if (!II) {
+ II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
+ KnownII = II;
+ }
+ Reader.markIdentifierUpToDate(II);
+ II->setIsFromAST();
+
+ // Set or check the various bits in the IdentifierInfo structure.
+ // Token IDs are read-only.
+ if (HasRevertedTokenIDToIdentifier)
+ II->RevertTokenIDToIdentifier();
+ II->setObjCOrBuiltinID(ObjCOrBuiltinID);
+ assert(II->isExtensionToken() == ExtensionToken &&
+ "Incorrect extension token flag");
+ (void)ExtensionToken;
+ if (Poisoned)
+ II->setIsPoisoned(true);
+ assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
+ "Incorrect C++ operator keyword flag");
+ (void)CPlusPlusOperatorKeyword;
+
+ // If this identifier is a macro, deserialize the macro
+ // definition.
+ if (hadMacroDefinition) {
+ SmallVector<MacroID, 4> MacroIDs;
+ while (uint32_t LocalID = ReadUnalignedLE32(d)) {
+ MacroIDs.push_back(Reader.getGlobalMacroID(F, LocalID));
+ DataLen -= 4;
+ }
+ DataLen -= 4;
+ Reader.setIdentifierIsMacro(II, MacroIDs);
+ }
+
+ Reader.SetIdentifierInfo(ID, II);
+
+ // Read all of the declarations visible at global scope with this
+ // name.
+ if (DataLen > 0) {
+ SmallVector<uint32_t, 4> DeclIDs;
+ for (; DataLen > 0; DataLen -= 4)
+ DeclIDs.push_back(Reader.getGlobalDeclID(F, ReadUnalignedLE32(d)));
+ Reader.SetGloballyVisibleDecls(II, DeclIDs);
+ }
+
+ return II;
+}
+
+unsigned
+ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) const {
+ llvm::FoldingSetNodeID ID;
+ ID.AddInteger(Key.Kind);
+
+ switch (Key.Kind) {
+ case DeclarationName::Identifier:
+ case DeclarationName::CXXLiteralOperatorName:
+ ID.AddString(((IdentifierInfo*)Key.Data)->getName());
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ ID.AddInteger(serialization::ComputeHash(Selector(Key.Data)));
+ break;
+ case DeclarationName::CXXOperatorName:
+ ID.AddInteger((OverloadedOperatorKind)Key.Data);
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+
+ return ID.ComputeHash();
+}
+
+ASTDeclContextNameLookupTrait::internal_key_type
+ASTDeclContextNameLookupTrait::GetInternalKey(
+ const external_key_type& Name) const {
+ DeclNameKey Key;
+ Key.Kind = Name.getNameKind();
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ Key.Data = (uint64_t)Name.getAsIdentifierInfo();
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ Key.Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr();
+ break;
+ case DeclarationName::CXXOperatorName:
+ Key.Data = Name.getCXXOverloadedOperator();
+ break;
+ case DeclarationName::CXXLiteralOperatorName:
+ Key.Data = (uint64_t)Name.getCXXLiteralIdentifier();
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ case DeclarationName::CXXUsingDirective:
+ Key.Data = 0;
+ break;
+ }
+
+ return Key;
+}
+
+std::pair<unsigned, unsigned>
+ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
+ using namespace clang::io;
+ unsigned KeyLen = ReadUnalignedLE16(d);
+ unsigned DataLen = ReadUnalignedLE16(d);
+ return std::make_pair(KeyLen, DataLen);
+}
+
+ASTDeclContextNameLookupTrait::internal_key_type
+ASTDeclContextNameLookupTrait::ReadKey(const unsigned char* d, unsigned) {
+ using namespace clang::io;
+
+ DeclNameKey Key;
+ Key.Kind = (DeclarationName::NameKind)*d++;
+ switch (Key.Kind) {
+ case DeclarationName::Identifier:
+ Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ Key.Data =
+ (uint64_t)Reader.getLocalSelector(F, ReadUnalignedLE32(d))
+ .getAsOpaquePtr();
+ break;
+ case DeclarationName::CXXOperatorName:
+ Key.Data = *d++; // OverloadedOperatorKind
+ break;
+ case DeclarationName::CXXLiteralOperatorName:
+ Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ case DeclarationName::CXXUsingDirective:
+ Key.Data = 0;
+ break;
+ }
+
+ return Key;
+}
+
+ASTDeclContextNameLookupTrait::data_type
+ASTDeclContextNameLookupTrait::ReadData(internal_key_type,
+ const unsigned char* d,
+ unsigned DataLen) {
+ using namespace clang::io;
+ unsigned NumDecls = ReadUnalignedLE16(d);
+ LE32DeclID *Start = (LE32DeclID *)d;
+ return std::make_pair(Start, Start + NumDecls);
+}
+
+bool ASTReader::ReadDeclContextStorage(ModuleFile &M,
+ llvm::BitstreamCursor &Cursor,
+ const std::pair<uint64_t, uint64_t> &Offsets,
+ DeclContextInfo &Info) {
+ SavedStreamPosition SavedPosition(Cursor);
+ // First the lexical decls.
+ if (Offsets.first != 0) {
+ Cursor.JumpToBit(Offsets.first);
+
+ RecordData Record;
+ const char *Blob;
+ unsigned BlobLen;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);
+ if (RecCode != DECL_CONTEXT_LEXICAL) {
+ Error("Expected lexical block");
+ return true;
+ }
+
+ Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair*>(Blob);
+ Info.NumLexicalDecls = BlobLen / sizeof(KindDeclIDPair);
+ }
+
+ // Now the lookup table.
+ if (Offsets.second != 0) {
+ Cursor.JumpToBit(Offsets.second);
+
+ RecordData Record;
+ const char *Blob;
+ unsigned BlobLen;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);
+ if (RecCode != DECL_CONTEXT_VISIBLE) {
+ Error("Expected visible lookup table block");
+ return true;
+ }
+ Info.NameLookupTableData
+ = ASTDeclContextNameLookupTable::Create(
+ (const unsigned char *)Blob + Record[0],
+ (const unsigned char *)Blob,
+ ASTDeclContextNameLookupTrait(*this, M));
+ }
+
+ return false;
+}
+
+void ASTReader::Error(StringRef Msg) {
+ Error(diag::err_fe_pch_malformed, Msg);
+}
+
+void ASTReader::Error(unsigned DiagID,
+ StringRef Arg1, StringRef Arg2) {
+ if (Diags.isDiagnosticInFlight())
+ Diags.SetDelayedDiagnostic(DiagID, Arg1, Arg2);
+ else
+ Diag(DiagID) << Arg1 << Arg2;
+}
+
+//===----------------------------------------------------------------------===//
+// Source Manager Deserialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Read the line table in the source manager block.
+/// \returns true if there was an error.
+bool ASTReader::ParseLineTable(ModuleFile &F,
+ SmallVectorImpl<uint64_t> &Record) {
+ unsigned Idx = 0;
+ LineTableInfo &LineTable = SourceMgr.getLineTable();
+
+ // Parse the file names
+ std::map<int, int> FileIDs;
+ for (int I = 0, N = Record[Idx++]; I != N; ++I) {
+ // Extract the file name
+ unsigned FilenameLen = Record[Idx++];
+ std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
+ Idx += FilenameLen;
+ MaybeAddSystemRootToFilename(F, Filename);
+ FileIDs[I] = LineTable.getLineTableFilenameID(Filename);
+ }
+
+ // Parse the line entries
+ std::vector<LineEntry> Entries;
+ while (Idx < Record.size()) {
+ int FID = Record[Idx++];
+ assert(FID >= 0 && "Serialized line entries for non-local file.");
+ // Remap FileID from 1-based old view.
+ FID += F.SLocEntryBaseID - 1;
+
+ // Extract the line entries
+ unsigned NumEntries = Record[Idx++];
+ assert(NumEntries && "Numentries is 00000");
+ Entries.clear();
+ Entries.reserve(NumEntries);
+ for (unsigned I = 0; I != NumEntries; ++I) {
+ unsigned FileOffset = Record[Idx++];
+ unsigned LineNo = Record[Idx++];
+ int FilenameID = FileIDs[Record[Idx++]];
+ SrcMgr::CharacteristicKind FileKind
+ = (SrcMgr::CharacteristicKind)Record[Idx++];
+ unsigned IncludeOffset = Record[Idx++];
+ Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
+ FileKind, IncludeOffset));
+ }
+ LineTable.AddEntry(FileID::get(FID), Entries);
+ }
+
+ return false;
+}
+
+/// \brief Read a source manager block
+bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
+ using namespace SrcMgr;
+
+ llvm::BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor;
+
+ // Set the source-location entry cursor to the current position in
+ // the stream. This cursor will be used to read the contents of the
+ // source manager block initially, and then lazily read
+ // source-location entries as needed.
+ SLocEntryCursor = F.Stream;
+
+ // The stream itself is going to skip over the source manager block.
+ if (F.Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return true;
+ }
+
+ // Enter the source manager block.
+ if (SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID)) {
+ Error("malformed source manager block record in AST file");
+ return true;
+ }
+
+ RecordData Record;
+ while (true) {
+ unsigned Code = SLocEntryCursor.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (SLocEntryCursor.ReadBlockEnd()) {
+ Error("error at end of Source Manager block in AST file");
+ return true;
+ }
+ return false;
+ }
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ SLocEntryCursor.ReadSubBlockID();
+ if (SLocEntryCursor.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return true;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ SLocEntryCursor.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read a record.
+ const char *BlobStart;
+ unsigned BlobLen;
+ Record.clear();
+ switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+ default: // Default behavior: ignore.
+ break;
+
+ case SM_SLOC_FILE_ENTRY:
+ case SM_SLOC_BUFFER_ENTRY:
+ case SM_SLOC_EXPANSION_ENTRY:
+ // Once we hit one of the source location entries, we're done.
+ return false;
+ }
+ }
+}
+
+/// \brief If a header file is not found at the path that we expect it to be
+/// and the PCH file was moved from its original location, try to resolve the
+/// file by assuming that header+PCH were moved together and the header is in
+/// the same place relative to the PCH.
+static std::string
+resolveFileRelativeToOriginalDir(const std::string &Filename,
+ const std::string &OriginalDir,
+ const std::string &CurrDir) {
+ assert(OriginalDir != CurrDir &&
+ "No point trying to resolve the file if the PCH dir didn't change");
+ using namespace llvm::sys;
+ SmallString<128> filePath(Filename);
+ fs::make_absolute(filePath);
+ assert(path::is_absolute(OriginalDir));
+ SmallString<128> currPCHPath(CurrDir);
+
+ path::const_iterator fileDirI = path::begin(path::parent_path(filePath)),
+ fileDirE = path::end(path::parent_path(filePath));
+ path::const_iterator origDirI = path::begin(OriginalDir),
+ origDirE = path::end(OriginalDir);
+ // Skip the common path components from filePath and OriginalDir.
+ while (fileDirI != fileDirE && origDirI != origDirE &&
+ *fileDirI == *origDirI) {
+ ++fileDirI;
+ ++origDirI;
+ }
+ for (; origDirI != origDirE; ++origDirI)
+ path::append(currPCHPath, "..");
+ path::append(currPCHPath, fileDirI, fileDirE);
+ path::append(currPCHPath, path::filename(Filename));
+ return currPCHPath.str();
+}
+
+bool ASTReader::ReadSLocEntry(int ID) {
+ if (ID == 0)
+ return false;
+
+ if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) {
+ Error("source location entry ID out-of-range for AST file");
+ return true;
+ }
+
+ ModuleFile *F = GlobalSLocEntryMap.find(-ID)->second;
+ F->SLocEntryCursor.JumpToBit(F->SLocEntryOffsets[ID - F->SLocEntryBaseID]);
+ llvm::BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor;
+ unsigned BaseOffset = F->SLocEntryBaseOffset;
+
+ ++NumSLocEntriesRead;
+ unsigned Code = SLocEntryCursor.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK ||
+ Code == llvm::bitc::ENTER_SUBBLOCK ||
+ Code == llvm::bitc::DEFINE_ABBREV) {
+ Error("incorrectly-formatted source location entry in AST file");
+ return true;
+ }
+
+ RecordData Record;
+ const char *BlobStart;
+ unsigned BlobLen;
+ switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+ default:
+ Error("incorrectly-formatted source location entry in AST file");
+ return true;
+
+ case SM_SLOC_FILE_ENTRY: {
+ // We will detect whether a file changed and return 'Failure' for it, but
+ // we will also try to fail gracefully by setting up the SLocEntry.
+ unsigned InputID = Record[4];
+ InputFile IF = getInputFile(*F, InputID);
+ const FileEntry *File = IF.getPointer();
+ bool OverriddenBuffer = IF.getInt();
+
+ if (!IF.getPointer())
+ return true;
+
+ SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
+ if (IncludeLoc.isInvalid() && F->Kind != MK_MainFile) {
+ // This is the module's main file.
+ IncludeLoc = getImportLocation(F);
+ }
+ SrcMgr::CharacteristicKind
+ FileCharacter = (SrcMgr::CharacteristicKind)Record[2];
+ FileID FID = SourceMgr.createFileID(File, IncludeLoc, FileCharacter,
+ ID, BaseOffset + Record[0]);
+ SrcMgr::FileInfo &FileInfo =
+ const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile());
+ FileInfo.NumCreatedFIDs = Record[5];
+ if (Record[3])
+ FileInfo.setHasLineDirectives();
+
+ const DeclID *FirstDecl = F->FileSortedDecls + Record[6];
+ unsigned NumFileDecls = Record[7];
+ if (NumFileDecls) {
+ assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?");
+ FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl,
+ NumFileDecls));
+ }
+
+ const SrcMgr::ContentCache *ContentCache
+ = SourceMgr.getOrCreateContentCache(File,
+ /*isSystemFile=*/FileCharacter != SrcMgr::C_User);
+ if (OverriddenBuffer && !ContentCache->BufferOverridden &&
+ ContentCache->ContentsEntry == ContentCache->OrigEntry) {
+ unsigned Code = SLocEntryCursor.ReadCode();
+ Record.clear();
+ unsigned RecCode
+ = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+
+ if (RecCode != SM_SLOC_BUFFER_BLOB) {
+ Error("AST record has invalid code");
+ return true;
+ }
+
+ llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),
+ File->getName());
+ SourceMgr.overrideFileContents(File, Buffer);
+ }
+
+ break;
+ }
+
+ case SM_SLOC_BUFFER_ENTRY: {
+ const char *Name = BlobStart;
+ unsigned Offset = Record[0];
+ SrcMgr::CharacteristicKind
+ FileCharacter = (SrcMgr::CharacteristicKind)Record[2];
+ SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
+ if (IncludeLoc.isInvalid() && F->Kind == MK_Module) {
+ IncludeLoc = getImportLocation(F);
+ }
+ unsigned Code = SLocEntryCursor.ReadCode();
+ Record.clear();
+ unsigned RecCode
+ = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+
+ if (RecCode != SM_SLOC_BUFFER_BLOB) {
+ Error("AST record has invalid code");
+ return true;
+ }
+
+ llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),
+ Name);
+ SourceMgr.createFileIDForMemBuffer(Buffer, FileCharacter, ID,
+ BaseOffset + Offset, IncludeLoc);
+ break;
+ }
+
+ case SM_SLOC_EXPANSION_ENTRY: {
+ SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1]);
+ SourceMgr.createExpansionLoc(SpellingLoc,
+ ReadSourceLocation(*F, Record[2]),
+ ReadSourceLocation(*F, Record[3]),
+ Record[4],
+ ID,
+ BaseOffset + Record[0]);
+ break;
+ }
+ }
+
+ return false;
+}
+
+std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) {
+ if (ID == 0)
+ return std::make_pair(SourceLocation(), "");
+
+ if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) {
+ Error("source location entry ID out-of-range for AST file");
+ return std::make_pair(SourceLocation(), "");
+ }
+
+ // Find which module file this entry lands in.
+ ModuleFile *M = GlobalSLocEntryMap.find(-ID)->second;
+ if (M->Kind != MK_Module)
+ return std::make_pair(SourceLocation(), "");
+
+ // FIXME: Can we map this down to a particular submodule? That would be
+ // ideal.
+ return std::make_pair(M->ImportLoc, llvm::sys::path::stem(M->FileName));
+}
+
+/// \brief Find the location where the module F is imported.
+SourceLocation ASTReader::getImportLocation(ModuleFile *F) {
+ if (F->ImportLoc.isValid())
+ return F->ImportLoc;
+
+ // Otherwise we have a PCH. It's considered to be "imported" at the first
+ // location of its includer.
+ if (F->ImportedBy.empty() || !F->ImportedBy[0]) {
+ // Main file is the importer. We assume that it is the first entry in the
+ // entry table. We can't ask the manager, because at the time of PCH loading
+ // the main file entry doesn't exist yet.
+ // The very first entry is the invalid instantiation loc, which takes up
+ // offsets 0 and 1.
+ return SourceLocation::getFromRawEncoding(2U);
+ }
+ //return F->Loaders[0]->FirstLoc;
+ return F->ImportedBy[0]->FirstLoc;
+}
+
+/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
+/// specified cursor. Read the abbreviations that are at the top of the block
+/// and then leave the cursor pointing into the block.
+bool ASTReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
+ unsigned BlockID) {
+ if (Cursor.EnterSubBlock(BlockID)) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+
+ while (true) {
+ uint64_t Offset = Cursor.GetCurrentBitNo();
+ unsigned Code = Cursor.ReadCode();
+
+ // We expect all abbrevs to be at the start of the block.
+ if (Code != llvm::bitc::DEFINE_ABBREV) {
+ Cursor.JumpToBit(Offset);
+ return false;
+ }
+ Cursor.ReadAbbrevRecord();
+ }
+}
+
+void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,
+ MacroInfo *Hint) {
+ llvm::BitstreamCursor &Stream = F.MacroCursor;
+
+ // Keep track of where we are in the stream, then jump back there
+ // after reading this macro.
+ SavedStreamPosition SavedPosition(Stream);
+
+ Stream.JumpToBit(Offset);
+ RecordData Record;
+ SmallVector<IdentifierInfo*, 16> MacroArgs;
+ MacroInfo *Macro = 0;
+
+ // RAII object to add the loaded macro information once we're done
+ // adding tokens.
+ struct AddLoadedMacroInfoRAII {
+ Preprocessor &PP;
+ MacroInfo *Hint;
+ MacroInfo *MI;
+ IdentifierInfo *II;
+
+ AddLoadedMacroInfoRAII(Preprocessor &PP, MacroInfo *Hint)
+ : PP(PP), Hint(Hint), MI(), II() { }
+ ~AddLoadedMacroInfoRAII( ) {
+ if (MI) {
+ // Finally, install the macro.
+ PP.addLoadedMacroInfo(II, MI, Hint);
+ }
+ }
+ } AddLoadedMacroInfo(PP, Hint);
+
+ while (true) {
+ unsigned Code = Stream.ReadCode();
+ switch (Code) {
+ case llvm::bitc::END_BLOCK:
+ return;
+
+ case llvm::bitc::ENTER_SUBBLOCK:
+ // No known subblocks, always skip them.
+ Stream.ReadSubBlockID();
+ if (Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return;
+ }
+ continue;
+
+ case llvm::bitc::DEFINE_ABBREV:
+ Stream.ReadAbbrevRecord();
+ continue;
+ default: break;
+ }
+
+ // Read a record.
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ Record.clear();
+ PreprocessorRecordTypes RecType =
+ (PreprocessorRecordTypes)Stream.ReadRecord(Code, Record, BlobStart,
+ BlobLen);
+ switch (RecType) {
+ case PP_MACRO_OBJECT_LIKE:
+ case PP_MACRO_FUNCTION_LIKE: {
+ // If we already have a macro, that means that we've hit the end
+ // of the definition of the macro we were looking for. We're
+ // done.
+ if (Macro)
+ return;
+
+ IdentifierInfo *II = getLocalIdentifier(F, Record[0]);
+ if (II == 0) {
+ Error("macro must have a name in AST file");
+ return;
+ }
+
+ unsigned GlobalID = getGlobalMacroID(F, Record[1]);
+
+ // If this macro has already been loaded, don't do so again.
+ if (MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS])
+ return;
+
+ SubmoduleID GlobalSubmoduleID = getGlobalSubmoduleID(F, Record[2]);
+ unsigned NextIndex = 3;
+ SourceLocation Loc = ReadSourceLocation(F, Record, NextIndex);
+ MacroInfo *MI = PP.AllocateMacroInfo(Loc);
+
+ // Record this macro.
+ MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS] = MI;
+
+ SourceLocation UndefLoc = ReadSourceLocation(F, Record, NextIndex);
+ if (UndefLoc.isValid())
+ MI->setUndefLoc(UndefLoc);
+
+ MI->setIsUsed(Record[NextIndex++]);
+ MI->setIsFromAST();
+
+ bool IsPublic = Record[NextIndex++];
+ MI->setVisibility(IsPublic, ReadSourceLocation(F, Record, NextIndex));
+
+ if (RecType == PP_MACRO_FUNCTION_LIKE) {
+ // Decode function-like macro info.
+ bool isC99VarArgs = Record[NextIndex++];
+ bool isGNUVarArgs = Record[NextIndex++];
+ bool hasCommaPasting = Record[NextIndex++];
+ MacroArgs.clear();
+ unsigned NumArgs = Record[NextIndex++];
+ for (unsigned i = 0; i != NumArgs; ++i)
+ MacroArgs.push_back(getLocalIdentifier(F, Record[NextIndex++]));
+
+ // Install function-like macro info.
+ MI->setIsFunctionLike();
+ if (isC99VarArgs) MI->setIsC99Varargs();
+ if (isGNUVarArgs) MI->setIsGNUVarargs();
+ if (hasCommaPasting) MI->setHasCommaPasting();
+ MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
+ PP.getPreprocessorAllocator());
+ }
+
+ if (DeserializationListener)
+ DeserializationListener->MacroRead(GlobalID, MI);
+
+ // If an update record marked this as undefined, do so now.
+ // FIXME: Only if the submodule this update came from is visible?
+ MacroUpdatesMap::iterator Update = MacroUpdates.find(GlobalID);
+ if (Update != MacroUpdates.end()) {
+ if (MI->getUndefLoc().isInvalid()) {
+ for (unsigned I = 0, N = Update->second.size(); I != N; ++I) {
+ bool Hidden = false;
+ if (unsigned SubmoduleID = Update->second[I].first) {
+ if (Module *Owner = getSubmodule(SubmoduleID)) {
+ if (Owner->NameVisibility == Module::Hidden) {
+ // Note that this #undef is hidden.
+ Hidden = true;
+
+ // Record this hiding for later.
+ HiddenNamesMap[Owner].push_back(
+ HiddenName(II, MI, Update->second[I].second.UndefLoc));
+ }
+ }
+ }
+
+ if (!Hidden) {
+ MI->setUndefLoc(Update->second[I].second.UndefLoc);
+ if (PPMutationListener *Listener = PP.getPPMutationListener())
+ Listener->UndefinedMacro(MI);
+ break;
+ }
+ }
+ }
+ MacroUpdates.erase(Update);
+ }
+
+ // Determine whether this macro definition is visible.
+ bool Hidden = !MI->isPublic();
+ if (!Hidden && GlobalSubmoduleID) {
+ if (Module *Owner = getSubmodule(GlobalSubmoduleID)) {
+ if (Owner->NameVisibility == Module::Hidden) {
+ // The owning module is not visible, and this macro definition
+ // should not be, either.
+ Hidden = true;
+
+ // Note that this macro definition was hidden because its owning
+ // module is not yet visible.
+ HiddenNamesMap[Owner].push_back(HiddenName(II, MI));
+ }
+ }
+ }
+ MI->setHidden(Hidden);
+
+ // Make sure we install the macro once we're done.
+ AddLoadedMacroInfo.MI = MI;
+ AddLoadedMacroInfo.II = II;
+
+ // Remember that we saw this macro last so that we add the tokens that
+ // form its body to it.
+ Macro = MI;
+
+ if (NextIndex + 1 == Record.size() && PP.getPreprocessingRecord() &&
+ Record[NextIndex]) {
+ // We have a macro definition. Register the association
+ PreprocessedEntityID
+ GlobalID = getGlobalPreprocessedEntityID(F, Record[NextIndex]);
+ PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
+ PPRec.RegisterMacroDefinition(Macro,
+ PPRec.getPPEntityID(GlobalID-1, /*isLoaded=*/true));
+ }
+
+ ++NumMacrosRead;
+ break;
+ }
+
+ case PP_TOKEN: {
+ // If we see a TOKEN before a PP_MACRO_*, then the file is
+ // erroneous, just pretend we didn't see this.
+ if (Macro == 0) break;
+
+ Token Tok;
+ Tok.startToken();
+ Tok.setLocation(ReadSourceLocation(F, Record[0]));
+ Tok.setLength(Record[1]);
+ if (IdentifierInfo *II = getLocalIdentifier(F, Record[2]))
+ Tok.setIdentifierInfo(II);
+ Tok.setKind((tok::TokenKind)Record[3]);
+ Tok.setFlag((Token::TokenFlags)Record[4]);
+ Macro->AddTokenToBody(Tok);
+ break;
+ }
+ }
+ }
+}
+
+PreprocessedEntityID
+ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const {
+ ContinuousRangeMap<uint32_t, int, 2>::const_iterator
+ I = M.PreprocessedEntityRemap.find(LocalID - NUM_PREDEF_PP_ENTITY_IDS);
+ assert(I != M.PreprocessedEntityRemap.end()
+ && "Invalid index into preprocessed entity index remap");
+
+ return LocalID + I->second;
+}
+
+unsigned HeaderFileInfoTrait::ComputeHash(const char *path) {
+ return llvm::HashString(llvm::sys::path::filename(path));
+}
+
+HeaderFileInfoTrait::internal_key_type
+HeaderFileInfoTrait::GetInternalKey(const char *path) { return path; }
+
+bool HeaderFileInfoTrait::EqualKey(internal_key_type a, internal_key_type b) {
+ if (strcmp(a, b) == 0)
+ return true;
+
+ if (llvm::sys::path::filename(a) != llvm::sys::path::filename(b))
+ return false;
+
+ // Determine whether the actual files are equivalent.
+ bool Result = false;
+ if (llvm::sys::fs::equivalent(a, b, Result))
+ return false;
+
+ return Result;
+}
+
+std::pair<unsigned, unsigned>
+HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) {
+ unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
+ unsigned DataLen = (unsigned) *d++;
+ return std::make_pair(KeyLen + 1, DataLen);
+}
+
+HeaderFileInfoTrait::data_type
+HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d,
+ unsigned DataLen) {
+ const unsigned char *End = d + DataLen;
+ using namespace clang::io;
+ HeaderFileInfo HFI;
+ unsigned Flags = *d++;
+ HFI.isImport = (Flags >> 5) & 0x01;
+ HFI.isPragmaOnce = (Flags >> 4) & 0x01;
+ HFI.DirInfo = (Flags >> 2) & 0x03;
+ HFI.Resolved = (Flags >> 1) & 0x01;
+ HFI.IndexHeaderMapHeader = Flags & 0x01;
+ HFI.NumIncludes = ReadUnalignedLE16(d);
+ HFI.ControllingMacroID = Reader.getGlobalIdentifierID(M,
+ ReadUnalignedLE32(d));
+ if (unsigned FrameworkOffset = ReadUnalignedLE32(d)) {
+ // The framework offset is 1 greater than the actual offset,
+ // since 0 is used as an indicator for "no framework name".
+ StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);
+ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
+ }
+
+ assert(End == d && "Wrong data length in HeaderFileInfo deserialization");
+ (void)End;
+
+ // This HeaderFileInfo was externally loaded.
+ HFI.External = true;
+ return HFI;
+}
+
+void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ArrayRef<MacroID> IDs){
+ II->setHadMacroDefinition(true);
+ assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
+ PendingMacroIDs[II].append(IDs.begin(), IDs.end());
+}
+
+void ASTReader::ReadDefinedMacros() {
+ // Note that we are loading defined macros.
+ Deserializing Macros(this);
+
+ for (ModuleReverseIterator I = ModuleMgr.rbegin(),
+ E = ModuleMgr.rend(); I != E; ++I) {
+ llvm::BitstreamCursor &MacroCursor = (*I)->MacroCursor;
+
+ // If there was no preprocessor block, skip this file.
+ if (!MacroCursor.getBitStreamReader())
+ continue;
+
+ llvm::BitstreamCursor Cursor = MacroCursor;
+ Cursor.JumpToBit((*I)->MacroStartOffset);
+
+ RecordData Record;
+ while (true) {
+ unsigned Code = Cursor.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK)
+ break;
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ Cursor.ReadSubBlockID();
+ if (Cursor.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Cursor.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read a record.
+ const char *BlobStart;
+ unsigned BlobLen;
+ Record.clear();
+ switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+ default: // Default behavior: ignore.
+ break;
+
+ case PP_MACRO_OBJECT_LIKE:
+ case PP_MACRO_FUNCTION_LIKE:
+ getLocalIdentifier(**I, Record[0]);
+ break;
+
+ case PP_TOKEN:
+ // Ignore tokens.
+ break;
+ }
+ }
+ }
+}
+
+namespace {
+ /// \brief Visitor class used to look up identifirs in an AST file.
+ class IdentifierLookupVisitor {
+ StringRef Name;
+ unsigned PriorGeneration;
+ IdentifierInfo *Found;
+ public:
+ IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration)
+ : Name(Name), PriorGeneration(PriorGeneration), Found() { }
+
+ static bool visit(ModuleFile &M, void *UserData) {
+ IdentifierLookupVisitor *This
+ = static_cast<IdentifierLookupVisitor *>(UserData);
+
+ // If we've already searched this module file, skip it now.
+ if (M.Generation <= This->PriorGeneration)
+ return true;
+
+ ASTIdentifierLookupTable *IdTable
+ = (ASTIdentifierLookupTable *)M.IdentifierLookupTable;
+ if (!IdTable)
+ return false;
+
+ ASTIdentifierLookupTrait Trait(IdTable->getInfoObj().getReader(),
+ M, This->Found);
+
+ std::pair<const char*, unsigned> Key(This->Name.begin(),
+ This->Name.size());
+ ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Trait);
+ if (Pos == IdTable->end())
+ return false;
+
+ // Dereferencing the iterator has the effect of building the
+ // IdentifierInfo node and populating it with the various
+ // declarations it needs.
+ This->Found = *Pos;
+ return true;
+ }
+
+ // \brief Retrieve the identifier info found within the module
+ // files.
+ IdentifierInfo *getIdentifierInfo() const { return Found; }
+ };
+}
+
+void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {
+ // Note that we are loading an identifier.
+ Deserializing AnIdentifier(this);
+
+ unsigned PriorGeneration = 0;
+ if (getContext().getLangOpts().Modules)
+ PriorGeneration = IdentifierGeneration[&II];
+
+ IdentifierLookupVisitor Visitor(II.getName(), PriorGeneration);
+ ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
+ markIdentifierUpToDate(&II);
+}
+
+void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) {
+ if (!II)
+ return;
+
+ II->setOutOfDate(false);
+
+ // Update the generation for this identifier.
+ if (getContext().getLangOpts().Modules)
+ IdentifierGeneration[II] = CurrentGeneration;
+}
+
+llvm::PointerIntPair<const FileEntry *, 1, bool>
+ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
+ // If this ID is bogus, just return an empty input file.
+ if (ID == 0 || ID > F.InputFilesLoaded.size())
+ return InputFile();
+
+ // If we've already loaded this input file, return it.
+ if (F.InputFilesLoaded[ID-1].getPointer())
+ return F.InputFilesLoaded[ID-1];
+
+ // Go find this input file.
+ llvm::BitstreamCursor &Cursor = F.InputFilesCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(F.InputFileOffsets[ID-1]);
+
+ unsigned Code = Cursor.ReadCode();
+ RecordData Record;
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ switch ((InputFileRecordTypes)Cursor.ReadRecord(Code, Record,
+ &BlobStart, &BlobLen)) {
+ case INPUT_FILE: {
+ unsigned StoredID = Record[0];
+ assert(ID == StoredID && "Bogus stored ID or offset");
+ (void)StoredID;
+ off_t StoredSize = (off_t)Record[1];
+ time_t StoredTime = (time_t)Record[2];
+ bool Overridden = (bool)Record[3];
+
+ // Get the file entry for this input file.
+ StringRef OrigFilename(BlobStart, BlobLen);
+ std::string Filename = OrigFilename;
+ MaybeAddSystemRootToFilename(F, Filename);
+ const FileEntry *File
+ = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime)
+ : FileMgr.getFile(Filename, /*OpenFile=*/false);
+
+ // If we didn't find the file, resolve it relative to the
+ // original directory from which this AST file was created.
+ if (File == 0 && !F.OriginalDir.empty() && !CurrentDir.empty() &&
+ F.OriginalDir != CurrentDir) {
+ std::string Resolved = resolveFileRelativeToOriginalDir(Filename,
+ F.OriginalDir,
+ CurrentDir);
+ if (!Resolved.empty())
+ File = FileMgr.getFile(Resolved);
+ }
+
+ // For an overridden file, create a virtual file with the stored
+ // size/timestamp.
+ if (Overridden && File == 0) {
+ File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime);
+ }
+
+ if (File == 0) {
+ if (Complain) {
+ std::string ErrorStr = "could not find file '";
+ ErrorStr += Filename;
+ ErrorStr += "' referenced by AST file";
+ Error(ErrorStr.c_str());
+ }
+ return InputFile();
+ }
+
+ // Note that we've loaded this input file.
+ F.InputFilesLoaded[ID-1] = InputFile(File, Overridden);
+
+ // Check if there was a request to override the contents of the file
+ // that was part of the precompiled header. Overridding such a file
+ // can lead to problems when lexing using the source locations from the
+ // PCH.
+ SourceManager &SM = getSourceManager();
+ if (!Overridden && SM.isFileOverridden(File)) {
+ Error(diag::err_fe_pch_file_overridden, Filename);
+ // After emitting the diagnostic, recover by disabling the override so
+ // that the original file will be used.
+ SM.disableFileContentsOverride(File);
+ // The FileEntry is a virtual file entry with the size of the contents
+ // that would override the original contents. Set it to the original's
+ // size/time.
+ FileMgr.modifyFileEntry(const_cast<FileEntry*>(File),
+ StoredSize, StoredTime);
+ }
+
+ // For an overridden file, there is nothing to validate.
+ if (Overridden)
+ return InputFile(File, Overridden);
+
+ if ((StoredSize != File->getSize()
+#if !defined(LLVM_ON_WIN32)
+ // In our regression testing, the Windows file system seems to
+ // have inconsistent modification times that sometimes
+ // erroneously trigger this error-handling path.
+ || StoredTime != File->getModificationTime()
+#endif
+ )) {
+ if (Complain)
+ Error(diag::err_fe_pch_file_modified, Filename);
+
+ return InputFile();
+ }
+
+ return InputFile(File, Overridden);
+ }
+ }
+
+ return InputFile();
+}
+
+const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) {
+ ModuleFile &M = ModuleMgr.getPrimaryModule();
+ std::string Filename = filenameStrRef;
+ MaybeAddSystemRootToFilename(M, Filename);
+ const FileEntry *File = FileMgr.getFile(Filename);
+ if (File == 0 && !M.OriginalDir.empty() && !CurrentDir.empty() &&
+ M.OriginalDir != CurrentDir) {
+ std::string resolved = resolveFileRelativeToOriginalDir(Filename,
+ M.OriginalDir,
+ CurrentDir);
+ if (!resolved.empty())
+ File = FileMgr.getFile(resolved);
+ }
+
+ return File;
+}
+
+/// \brief If we are loading a relocatable PCH file, and the filename is
+/// not an absolute path, add the system root to the beginning of the file
+/// name.
+void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M,
+ std::string &Filename) {
+ // If this is not a relocatable PCH file, there's nothing to do.
+ if (!M.RelocatablePCH)
+ return;
+
+ if (Filename.empty() || llvm::sys::path::is_absolute(Filename))
+ return;
+
+ if (isysroot.empty()) {
+ // If no system root was given, default to '/'
+ Filename.insert(Filename.begin(), '/');
+ return;
+ }
+
+ unsigned Length = isysroot.size();
+ if (isysroot[Length - 1] != '/')
+ Filename.insert(Filename.begin(), '/');
+
+ Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end());
+}
+
+ASTReader::ASTReadResult
+ASTReader::ReadControlBlock(ModuleFile &F,
+ llvm::SmallVectorImpl<ImportedModule> &Loaded,
+ unsigned ClientLoadCapabilities) {
+ llvm::BitstreamCursor &Stream = F.Stream;
+
+ if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+
+ // Read all of the records and blocks in the control block.
+ RecordData Record;
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (Stream.ReadBlockEnd()) {
+ Error("error at end of control block in AST file");
+ return Failure;
+ }
+
+ // Validate all of the input files.
+ if (!DisableValidation) {
+ bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
+ for (unsigned I = 0, N = Record[0]; I < N; ++I)
+ if (!getInputFile(F, I+1, Complain).getPointer())
+ return OutOfDate;
+ }
+
+ return Success;
+ }
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ switch (Stream.ReadSubBlockID()) {
+ case INPUT_FILES_BLOCK_ID:
+ F.InputFilesCursor = Stream;
+ if (Stream.SkipBlock() || // Skip with the main cursor
+ // Read the abbreviations
+ ReadBlockAbbrevs(F.InputFilesCursor, INPUT_FILES_BLOCK_ID)) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+ continue;
+
+ default:
+ if (!Stream.SkipBlock())
+ continue;
+ break;
+ }
+
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read and process a record.
+ Record.clear();
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ switch ((ControlRecordTypes)Stream.ReadRecord(Code, Record,
+ &BlobStart, &BlobLen)) {
+ case METADATA: {
+ if (Record[0] != VERSION_MAJOR && !DisableValidation) {
+ if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
+ Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
+ : diag::warn_pch_version_too_new);
+ return VersionMismatch;
+ }
+
+ bool hasErrors = Record[5];
+ if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {
+ Diag(diag::err_pch_with_compiler_errors);
+ return HadErrors;
+ }
+
+ F.RelocatablePCH = Record[4];
+
+ const std::string &CurBranch = getClangFullRepositoryVersion();
+ StringRef ASTBranch(BlobStart, BlobLen);
+ if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {
+ if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
+ Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch;
+ return VersionMismatch;
+ }
+ break;
+ }
+
+ case IMPORTS: {
+ // Load each of the imported PCH files.
+ unsigned Idx = 0, N = Record.size();
+ while (Idx < N) {
+ // Read information about the AST file.
+ ModuleKind ImportedKind = (ModuleKind)Record[Idx++];
+ // The import location will be the local one for now; we will adjust
+ // all import locations of module imports after the global source
+ // location info are setup.
+ SourceLocation ImportLoc =
+ SourceLocation::getFromRawEncoding(Record[Idx++]);
+ unsigned Length = Record[Idx++];
+ SmallString<128> ImportedFile(Record.begin() + Idx,
+ Record.begin() + Idx + Length);
+ Idx += Length;
+
+ // Load the AST file.
+ switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded,
+ ClientLoadCapabilities)) {
+ case Failure: return Failure;
+ // If we have to ignore the dependency, we'll have to ignore this too.
+ case OutOfDate: return OutOfDate;
+ case VersionMismatch: return VersionMismatch;
+ case ConfigurationMismatch: return ConfigurationMismatch;
+ case HadErrors: return HadErrors;
+ case Success: break;
+ }
+ }
+ break;
+ }
+
+ case LANGUAGE_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
+ if (Listener && &F == *ModuleMgr.begin() &&
+ ParseLanguageOptions(Record, Complain, *Listener) &&
+ !DisableValidation)
+ return ConfigurationMismatch;
+ break;
+ }
+
+ case TARGET_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+ if (Listener && &F == *ModuleMgr.begin() &&
+ ParseTargetOptions(Record, Complain, *Listener) &&
+ !DisableValidation)
+ return ConfigurationMismatch;
+ break;
+ }
+
+ case DIAGNOSTIC_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+ if (Listener && &F == *ModuleMgr.begin() &&
+ ParseDiagnosticOptions(Record, Complain, *Listener) &&
+ !DisableValidation)
+ return ConfigurationMismatch;
+ break;
+ }
+
+ case FILE_SYSTEM_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+ if (Listener && &F == *ModuleMgr.begin() &&
+ ParseFileSystemOptions(Record, Complain, *Listener) &&
+ !DisableValidation)
+ return ConfigurationMismatch;
+ break;
+ }
+
+ case HEADER_SEARCH_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+ if (Listener && &F == *ModuleMgr.begin() &&
+ ParseHeaderSearchOptions(Record, Complain, *Listener) &&
+ !DisableValidation)
+ return ConfigurationMismatch;
+ break;
+ }
+
+ case PREPROCESSOR_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+ if (Listener && &F == *ModuleMgr.begin() &&
+ ParsePreprocessorOptions(Record, Complain, *Listener,
+ SuggestedPredefines) &&
+ !DisableValidation)
+ return ConfigurationMismatch;
+ break;
+ }
+
+ case ORIGINAL_FILE:
+ F.OriginalSourceFileID = FileID::get(Record[0]);
+ F.ActualOriginalSourceFileName.assign(BlobStart, BlobLen);
+ F.OriginalSourceFileName = F.ActualOriginalSourceFileName;
+ MaybeAddSystemRootToFilename(F, F.OriginalSourceFileName);
+ break;
+
+ case ORIGINAL_FILE_ID:
+ F.OriginalSourceFileID = FileID::get(Record[0]);
+ break;
+
+ case ORIGINAL_PCH_DIR:
+ F.OriginalDir.assign(BlobStart, BlobLen);
+ break;
+
+ case INPUT_FILE_OFFSETS:
+ F.InputFileOffsets = (const uint32_t *)BlobStart;
+ F.InputFilesLoaded.resize(Record[0]);
+ break;
+ }
+ }
+
+ Error("premature end of bitstream in AST file");
+ return Failure;
+}
+
+bool ASTReader::ReadASTBlock(ModuleFile &F) {
+ llvm::BitstreamCursor &Stream = F.Stream;
+
+ if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
+ Error("malformed block record in AST file");
+ return true;
+ }
+
+ // Read all of the records and blocks for the AST file.
+ RecordData Record;
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (Stream.ReadBlockEnd()) {
+ Error("error at end of module block in AST file");
+ return true;
+ }
+
+ DeclContext *DC = Context.getTranslationUnitDecl();
+ if (!DC->hasExternalVisibleStorage() && DC->hasExternalLexicalStorage())
+ DC->setMustBuildLookupTable();
+
+ return false;
+ }
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ switch (Stream.ReadSubBlockID()) {
+ case DECLTYPES_BLOCK_ID:
+ // We lazily load the decls block, but we want to set up the
+ // DeclsCursor cursor to point into it. Clone our current bitcode
+ // cursor to it, enter the block and read the abbrevs in that block.
+ // With the main cursor, we just skip over it.
+ F.DeclsCursor = Stream;
+ if (Stream.SkipBlock() || // Skip with the main cursor.
+ // Read the abbrevs.
+ ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) {
+ Error("malformed block record in AST file");
+ return true;
+ }
+ break;
+
+ case DECL_UPDATES_BLOCK_ID:
+ if (Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return true;
+ }
+ break;
+
+ case PREPROCESSOR_BLOCK_ID:
+ F.MacroCursor = Stream;
+ if (!PP.getExternalSource())
+ PP.setExternalSource(this);
+
+ if (Stream.SkipBlock() ||
+ ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) {
+ Error("malformed block record in AST file");
+ return true;
+ }
+ F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo();
+ break;
+
+ case PREPROCESSOR_DETAIL_BLOCK_ID:
+ F.PreprocessorDetailCursor = Stream;
+ if (Stream.SkipBlock() ||
+ ReadBlockAbbrevs(F.PreprocessorDetailCursor,
+ PREPROCESSOR_DETAIL_BLOCK_ID)) {
+ Error("malformed preprocessor detail record in AST file");
+ return true;
+ }
+ F.PreprocessorDetailStartOffset
+ = F.PreprocessorDetailCursor.GetCurrentBitNo();
+
+ if (!PP.getPreprocessingRecord())
+ PP.createPreprocessingRecord();
+ if (!PP.getPreprocessingRecord()->getExternalSource())
+ PP.getPreprocessingRecord()->SetExternalSource(*this);
+ break;
+
+ case SOURCE_MANAGER_BLOCK_ID:
+ if (ReadSourceManagerBlock(F))
+ return true;
+ break;
+
+ case SUBMODULE_BLOCK_ID:
+ if (ReadSubmoduleBlock(F))
+ return true;
+ break;
+
+ case COMMENTS_BLOCK_ID: {
+ llvm::BitstreamCursor C = Stream;
+ if (Stream.SkipBlock() ||
+ ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) {
+ Error("malformed comments block in AST file");
+ return true;
+ }
+ CommentsCursors.push_back(std::make_pair(C, &F));
+ break;
+ }
+
+ default:
+ if (!Stream.SkipBlock())
+ break;
+ Error("malformed block record in AST file");
+ return true;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read and process a record.
+ Record.clear();
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ switch ((ASTRecordTypes)Stream.ReadRecord(Code, Record,
+ &BlobStart, &BlobLen)) {
+ default: // Default behavior: ignore.
+ break;
+
+ case TYPE_OFFSET: {
+ if (F.LocalNumTypes != 0) {
+ Error("duplicate TYPE_OFFSET record in AST file");
+ return true;
+ }
+ F.TypeOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumTypes = Record[0];
+ unsigned LocalBaseTypeIndex = Record[1];
+ F.BaseTypeIndex = getTotalNumTypes();
+
+ if (F.LocalNumTypes > 0) {
+ // Introduce the global -> local mapping for types within this module.
+ GlobalTypeMap.insert(std::make_pair(getTotalNumTypes(), &F));
+
+ // Introduce the local -> global mapping for types within this module.
+ F.TypeRemap.insertOrReplace(
+ std::make_pair(LocalBaseTypeIndex,
+ F.BaseTypeIndex - LocalBaseTypeIndex));
+
+ TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes);
+ }
+ break;
+ }
+
+ case DECL_OFFSET: {
+ if (F.LocalNumDecls != 0) {
+ Error("duplicate DECL_OFFSET record in AST file");
+ return true;
+ }
+ F.DeclOffsets = (const DeclOffset *)BlobStart;
+ F.LocalNumDecls = Record[0];
+ unsigned LocalBaseDeclID = Record[1];
+ F.BaseDeclID = getTotalNumDecls();
+
+ if (F.LocalNumDecls > 0) {
+ // Introduce the global -> local mapping for declarations within this
+ // module.
+ GlobalDeclMap.insert(
+ std::make_pair(getTotalNumDecls() + NUM_PREDEF_DECL_IDS, &F));
+
+ // Introduce the local -> global mapping for declarations within this
+ // module.
+ F.DeclRemap.insertOrReplace(
+ std::make_pair(LocalBaseDeclID, F.BaseDeclID - LocalBaseDeclID));
+
+ // Introduce the global -> local mapping for declarations within this
+ // module.
+ F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID;
+
+ DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);
+ }
+ break;
+ }
+
+ case TU_UPDATE_LEXICAL: {
+ DeclContext *TU = Context.getTranslationUnitDecl();
+ DeclContextInfo &Info = F.DeclContextInfos[TU];
+ Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair *>(BlobStart);
+ Info.NumLexicalDecls
+ = static_cast<unsigned int>(BlobLen / sizeof(KindDeclIDPair));
+ TU->setHasExternalLexicalStorage(true);
+ break;
+ }
+
+ case UPDATE_VISIBLE: {
+ unsigned Idx = 0;
+ serialization::DeclID ID = ReadDeclID(F, Record, Idx);
+ ASTDeclContextNameLookupTable *Table =
+ ASTDeclContextNameLookupTable::Create(
+ (const unsigned char *)BlobStart + Record[Idx++],
+ (const unsigned char *)BlobStart,
+ ASTDeclContextNameLookupTrait(*this, F));
+ if (ID == PREDEF_DECL_TRANSLATION_UNIT_ID) { // Is it the TU?
+ DeclContext *TU = Context.getTranslationUnitDecl();
+ F.DeclContextInfos[TU].NameLookupTableData = Table;
+ TU->setHasExternalVisibleStorage(true);
+ } else
+ PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F));
+ break;
+ }
+
+ case IDENTIFIER_TABLE:
+ F.IdentifierTableData = BlobStart;
+ if (Record[0]) {
+ F.IdentifierLookupTable
+ = ASTIdentifierLookupTable::Create(
+ (const unsigned char *)F.IdentifierTableData + Record[0],
+ (const unsigned char *)F.IdentifierTableData,
+ ASTIdentifierLookupTrait(*this, F));
+
+ PP.getIdentifierTable().setExternalIdentifierLookup(this);
+ }
+ break;
+
+ case IDENTIFIER_OFFSET: {
+ if (F.LocalNumIdentifiers != 0) {
+ Error("duplicate IDENTIFIER_OFFSET record in AST file");
+ return true;
+ }
+ F.IdentifierOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumIdentifiers = Record[0];
+ unsigned LocalBaseIdentifierID = Record[1];
+ F.BaseIdentifierID = getTotalNumIdentifiers();
+
+ if (F.LocalNumIdentifiers > 0) {
+ // Introduce the global -> local mapping for identifiers within this
+ // module.
+ GlobalIdentifierMap.insert(std::make_pair(getTotalNumIdentifiers() + 1,
+ &F));
+
+ // Introduce the local -> global mapping for identifiers within this
+ // module.
+ F.IdentifierRemap.insertOrReplace(
+ std::make_pair(LocalBaseIdentifierID,
+ F.BaseIdentifierID - LocalBaseIdentifierID));
+
+ IdentifiersLoaded.resize(IdentifiersLoaded.size()
+ + F.LocalNumIdentifiers);
+ }
+ break;
+ }
+
+ case EXTERNAL_DEFINITIONS:
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ ExternalDefinitions.push_back(getGlobalDeclID(F, Record[I]));
+ break;
+
+ case SPECIAL_TYPES:
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ SpecialTypes.push_back(getGlobalTypeID(F, Record[I]));
+ break;
+
+ case STATISTICS:
+ TotalNumStatements += Record[0];
+ TotalNumMacros += Record[1];
+ TotalLexicalDeclContexts += Record[2];
+ TotalVisibleDeclContexts += Record[3];
+ break;
+
+ case UNUSED_FILESCOPED_DECLS:
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ UnusedFileScopedDecls.push_back(getGlobalDeclID(F, Record[I]));
+ break;
+
+ case DELEGATING_CTORS:
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ DelegatingCtorDecls.push_back(getGlobalDeclID(F, Record[I]));
+ break;
+
+ case WEAK_UNDECLARED_IDENTIFIERS:
+ if (Record.size() % 4 != 0) {
+ Error("invalid weak identifiers record");
+ return true;
+ }
+
+ // FIXME: Ignore weak undeclared identifiers from non-original PCH
+ // files. This isn't the way to do it :)
+ WeakUndeclaredIdentifiers.clear();
+
+ // Translate the weak, undeclared identifiers into global IDs.
+ for (unsigned I = 0, N = Record.size(); I < N; /* in loop */) {
+ WeakUndeclaredIdentifiers.push_back(
+ getGlobalIdentifierID(F, Record[I++]));
+ WeakUndeclaredIdentifiers.push_back(
+ getGlobalIdentifierID(F, Record[I++]));
+ WeakUndeclaredIdentifiers.push_back(
+ ReadSourceLocation(F, Record, I).getRawEncoding());
+ WeakUndeclaredIdentifiers.push_back(Record[I++]);
+ }
+ break;
+
+ case LOCALLY_SCOPED_EXTERNAL_DECLS:
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ LocallyScopedExternalDecls.push_back(getGlobalDeclID(F, Record[I]));
+ break;
+
+ case SELECTOR_OFFSETS: {
+ F.SelectorOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumSelectors = Record[0];
+ unsigned LocalBaseSelectorID = Record[1];
+ F.BaseSelectorID = getTotalNumSelectors();
+
+ if (F.LocalNumSelectors > 0) {
+ // Introduce the global -> local mapping for selectors within this
+ // module.
+ GlobalSelectorMap.insert(std::make_pair(getTotalNumSelectors()+1, &F));
+
+ // Introduce the local -> global mapping for selectors within this
+ // module.
+ F.SelectorRemap.insertOrReplace(
+ std::make_pair(LocalBaseSelectorID,
+ F.BaseSelectorID - LocalBaseSelectorID));
+
+ SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors);
+ }
+ break;
+ }
+
+ case METHOD_POOL:
+ F.SelectorLookupTableData = (const unsigned char *)BlobStart;
+ if (Record[0])
+ F.SelectorLookupTable
+ = ASTSelectorLookupTable::Create(
+ F.SelectorLookupTableData + Record[0],
+ F.SelectorLookupTableData,
+ ASTSelectorLookupTrait(*this, F));
+ TotalNumMethodPoolEntries += Record[1];
+ break;
+
+ case REFERENCED_SELECTOR_POOL:
+ if (!Record.empty()) {
+ for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) {
+ ReferencedSelectorsData.push_back(getGlobalSelectorID(F,
+ Record[Idx++]));
+ ReferencedSelectorsData.push_back(ReadSourceLocation(F, Record, Idx).
+ getRawEncoding());
+ }
+ }
+ break;
+
+ case PP_COUNTER_VALUE:
+ if (!Record.empty() && Listener)
+ Listener->ReadCounter(F, Record[0]);
+ break;
+
+ case FILE_SORTED_DECLS:
+ F.FileSortedDecls = (const DeclID *)BlobStart;
+ F.NumFileSortedDecls = Record[0];
+ break;
+
+ case SOURCE_LOCATION_OFFSETS: {
+ F.SLocEntryOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumSLocEntries = Record[0];
+ unsigned SLocSpaceSize = Record[1];
+ llvm::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) =
+ SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries,
+ SLocSpaceSize);
+ // Make our entry in the range map. BaseID is negative and growing, so
+ // we invert it. Because we invert it, though, we need the other end of
+ // the range.
+ unsigned RangeStart =
+ unsigned(-F.SLocEntryBaseID) - F.LocalNumSLocEntries + 1;
+ GlobalSLocEntryMap.insert(std::make_pair(RangeStart, &F));
+ F.FirstLoc = SourceLocation::getFromRawEncoding(F.SLocEntryBaseOffset);
+
+ // SLocEntryBaseOffset is lower than MaxLoadedOffset and decreasing.
+ assert((F.SLocEntryBaseOffset & (1U << 31U)) == 0);
+ GlobalSLocOffsetMap.insert(
+ std::make_pair(SourceManager::MaxLoadedOffset - F.SLocEntryBaseOffset
+ - SLocSpaceSize,&F));
+
+ // Initialize the remapping table.
+ // Invalid stays invalid.
+ F.SLocRemap.insert(std::make_pair(0U, 0));
+ // This module. Base was 2 when being compiled.
+ F.SLocRemap.insert(std::make_pair(2U,
+ static_cast<int>(F.SLocEntryBaseOffset - 2)));
+
+ TotalNumSLocEntries += F.LocalNumSLocEntries;
+ break;
+ }
+
+ case MODULE_OFFSET_MAP: {
+ // Additional remapping information.
+ const unsigned char *Data = (const unsigned char*)BlobStart;
+ const unsigned char *DataEnd = Data + BlobLen;
+
+ // Continuous range maps we may be updating in our module.
+ ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap);
+ ContinuousRangeMap<uint32_t, int, 2>::Builder
+ IdentifierRemap(F.IdentifierRemap);
+ ContinuousRangeMap<uint32_t, int, 2>::Builder
+ MacroRemap(F.MacroRemap);
+ ContinuousRangeMap<uint32_t, int, 2>::Builder
+ PreprocessedEntityRemap(F.PreprocessedEntityRemap);
+ ContinuousRangeMap<uint32_t, int, 2>::Builder
+ SubmoduleRemap(F.SubmoduleRemap);
+ ContinuousRangeMap<uint32_t, int, 2>::Builder
+ SelectorRemap(F.SelectorRemap);
+ ContinuousRangeMap<uint32_t, int, 2>::Builder DeclRemap(F.DeclRemap);
+ ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap);
+
+ while(Data < DataEnd) {
+ uint16_t Len = io::ReadUnalignedLE16(Data);
+ StringRef Name = StringRef((const char*)Data, Len);
+ Data += Len;
+ ModuleFile *OM = ModuleMgr.lookup(Name);
+ if (!OM) {
+ Error("SourceLocation remap refers to unknown module");
+ return true;
+ }
+
+ uint32_t SLocOffset = io::ReadUnalignedLE32(Data);
+ uint32_t IdentifierIDOffset = io::ReadUnalignedLE32(Data);
+ uint32_t MacroIDOffset = io::ReadUnalignedLE32(Data);
+ uint32_t PreprocessedEntityIDOffset = io::ReadUnalignedLE32(Data);
+ uint32_t SubmoduleIDOffset = io::ReadUnalignedLE32(Data);
+ uint32_t SelectorIDOffset = io::ReadUnalignedLE32(Data);
+ uint32_t DeclIDOffset = io::ReadUnalignedLE32(Data);
+ uint32_t TypeIndexOffset = io::ReadUnalignedLE32(Data);
+
+ // Source location offset is mapped to OM->SLocEntryBaseOffset.
+ SLocRemap.insert(std::make_pair(SLocOffset,
+ static_cast<int>(OM->SLocEntryBaseOffset - SLocOffset)));
+ IdentifierRemap.insert(
+ std::make_pair(IdentifierIDOffset,
+ OM->BaseIdentifierID - IdentifierIDOffset));
+ MacroRemap.insert(std::make_pair(MacroIDOffset,
+ OM->BaseMacroID - MacroIDOffset));
+ PreprocessedEntityRemap.insert(
+ std::make_pair(PreprocessedEntityIDOffset,
+ OM->BasePreprocessedEntityID - PreprocessedEntityIDOffset));
+ SubmoduleRemap.insert(std::make_pair(SubmoduleIDOffset,
+ OM->BaseSubmoduleID - SubmoduleIDOffset));
+ SelectorRemap.insert(std::make_pair(SelectorIDOffset,
+ OM->BaseSelectorID - SelectorIDOffset));
+ DeclRemap.insert(std::make_pair(DeclIDOffset,
+ OM->BaseDeclID - DeclIDOffset));
+
+ TypeRemap.insert(std::make_pair(TypeIndexOffset,
+ OM->BaseTypeIndex - TypeIndexOffset));
+
+ // Global -> local mappings.
+ F.GlobalToLocalDeclIDs[OM] = DeclIDOffset;
+ }
+ break;
+ }
+
+ case SOURCE_MANAGER_LINE_TABLE:
+ if (ParseLineTable(F, Record))
+ return true;
+ break;
+
+ case SOURCE_LOCATION_PRELOADS: {
+ // Need to transform from the local view (1-based IDs) to the global view,
+ // which is based off F.SLocEntryBaseID.
+ if (!F.PreloadSLocEntries.empty()) {
+ Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file");
+ return true;
+ }
+
+ F.PreloadSLocEntries.swap(Record);
+ break;
+ }
+
+ case EXT_VECTOR_DECLS:
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ ExtVectorDecls.push_back(getGlobalDeclID(F, Record[I]));
+ break;
+
+ case VTABLE_USES:
+ if (Record.size() % 3 != 0) {
+ Error("Invalid VTABLE_USES record");
+ return true;
+ }
+
+ // Later tables overwrite earlier ones.
+ // FIXME: Modules will have some trouble with this. This is clearly not
+ // the right way to do this.
+ VTableUses.clear();
+
+ for (unsigned Idx = 0, N = Record.size(); Idx != N; /* In loop */) {
+ VTableUses.push_back(getGlobalDeclID(F, Record[Idx++]));
+ VTableUses.push_back(
+ ReadSourceLocation(F, Record, Idx).getRawEncoding());
+ VTableUses.push_back(Record[Idx++]);
+ }
+ break;
+
+ case DYNAMIC_CLASSES:
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ DynamicClasses.push_back(getGlobalDeclID(F, Record[I]));
+ break;
+
+ case PENDING_IMPLICIT_INSTANTIATIONS:
+ if (PendingInstantiations.size() % 2 != 0) {
+ Error("Invalid existing PendingInstantiations");
+ return true;
+ }
+
+ if (Record.size() % 2 != 0) {
+ Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block");
+ return true;
+ }
+
+ for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
+ PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++]));
+ PendingInstantiations.push_back(
+ ReadSourceLocation(F, Record, I).getRawEncoding());
+ }
+ break;
+
+ case SEMA_DECL_REFS:
+ // Later tables overwrite earlier ones.
+ // FIXME: Modules will have some trouble with this.
+ SemaDeclRefs.clear();
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I]));
+ break;
+
+ case PPD_ENTITIES_OFFSETS: {
+ F.PreprocessedEntityOffsets = (const PPEntityOffset *)BlobStart;
+ assert(BlobLen % sizeof(PPEntityOffset) == 0);
+ F.NumPreprocessedEntities = BlobLen / sizeof(PPEntityOffset);
+
+ unsigned LocalBasePreprocessedEntityID = Record[0];
+
+ unsigned StartingID;
+ if (!PP.getPreprocessingRecord())
+ PP.createPreprocessingRecord();
+ if (!PP.getPreprocessingRecord()->getExternalSource())
+ PP.getPreprocessingRecord()->SetExternalSource(*this);
+ StartingID
+ = PP.getPreprocessingRecord()
+ ->allocateLoadedEntities(F.NumPreprocessedEntities);
+ F.BasePreprocessedEntityID = StartingID;
+
+ if (F.NumPreprocessedEntities > 0) {
+ // Introduce the global -> local mapping for preprocessed entities in
+ // this module.
+ GlobalPreprocessedEntityMap.insert(std::make_pair(StartingID, &F));
+
+ // Introduce the local -> global mapping for preprocessed entities in
+ // this module.
+ F.PreprocessedEntityRemap.insertOrReplace(
+ std::make_pair(LocalBasePreprocessedEntityID,
+ F.BasePreprocessedEntityID - LocalBasePreprocessedEntityID));
+ }
+
+ break;
+ }
+
+ case DECL_UPDATE_OFFSETS: {
+ if (Record.size() % 2 != 0) {
+ Error("invalid DECL_UPDATE_OFFSETS block in AST file");
+ return true;
+ }
+ for (unsigned I = 0, N = Record.size(); I != N; I += 2)
+ DeclUpdateOffsets[getGlobalDeclID(F, Record[I])]
+ .push_back(std::make_pair(&F, Record[I+1]));
+ break;
+ }
+
+ case DECL_REPLACEMENTS: {
+ if (Record.size() % 3 != 0) {
+ Error("invalid DECL_REPLACEMENTS block in AST file");
+ return true;
+ }
+ for (unsigned I = 0, N = Record.size(); I != N; I += 3)
+ ReplacedDecls[getGlobalDeclID(F, Record[I])]
+ = ReplacedDeclInfo(&F, Record[I+1], Record[I+2]);
+ break;
+ }
+
+ case OBJC_CATEGORIES_MAP: {
+ if (F.LocalNumObjCCategoriesInMap != 0) {
+ Error("duplicate OBJC_CATEGORIES_MAP record in AST file");
+ return true;
+ }
+
+ F.LocalNumObjCCategoriesInMap = Record[0];
+ F.ObjCCategoriesMap = (const ObjCCategoriesInfo *)BlobStart;
+ break;
+ }
+
+ case OBJC_CATEGORIES:
+ F.ObjCCategories.swap(Record);
+ break;
+
+ case CXX_BASE_SPECIFIER_OFFSETS: {
+ if (F.LocalNumCXXBaseSpecifiers != 0) {
+ Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file");
+ return true;
+ }
+
+ F.LocalNumCXXBaseSpecifiers = Record[0];
+ F.CXXBaseSpecifiersOffsets = (const uint32_t *)BlobStart;
+ NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers;
+ break;
+ }
+
+ case DIAG_PRAGMA_MAPPINGS:
+ if (F.PragmaDiagMappings.empty())
+ F.PragmaDiagMappings.swap(Record);
+ else
+ F.PragmaDiagMappings.insert(F.PragmaDiagMappings.end(),
+ Record.begin(), Record.end());
+ break;
+
+ case CUDA_SPECIAL_DECL_REFS:
+ // Later tables overwrite earlier ones.
+ // FIXME: Modules will have trouble with this.
+ CUDASpecialDeclRefs.clear();
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ CUDASpecialDeclRefs.push_back(getGlobalDeclID(F, Record[I]));
+ break;
+
+ case HEADER_SEARCH_TABLE: {
+ F.HeaderFileInfoTableData = BlobStart;
+ F.LocalNumHeaderFileInfos = Record[1];
+ F.HeaderFileFrameworkStrings = BlobStart + Record[2];
+ if (Record[0]) {
+ F.HeaderFileInfoTable
+ = HeaderFileInfoLookupTable::Create(
+ (const unsigned char *)F.HeaderFileInfoTableData + Record[0],
+ (const unsigned char *)F.HeaderFileInfoTableData,
+ HeaderFileInfoTrait(*this, F,
+ &PP.getHeaderSearchInfo(),
+ BlobStart + Record[2]));
+
+ PP.getHeaderSearchInfo().SetExternalSource(this);
+ if (!PP.getHeaderSearchInfo().getExternalLookup())
+ PP.getHeaderSearchInfo().SetExternalLookup(this);
+ }
+ break;
+ }
+
+ case FP_PRAGMA_OPTIONS:
+ // Later tables overwrite earlier ones.
+ FPPragmaOptions.swap(Record);
+ break;
+
+ case OPENCL_EXTENSIONS:
+ // Later tables overwrite earlier ones.
+ OpenCLExtensions.swap(Record);
+ break;
+
+ case TENTATIVE_DEFINITIONS:
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ TentativeDefinitions.push_back(getGlobalDeclID(F, Record[I]));
+ break;
+
+ case KNOWN_NAMESPACES:
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ KnownNamespaces.push_back(getGlobalDeclID(F, Record[I]));
+ break;
+
+ case IMPORTED_MODULES: {
+ if (F.Kind != MK_Module) {
+ // If we aren't loading a module (which has its own exports), make
+ // all of the imported modules visible.
+ // FIXME: Deal with macros-only imports.
+ for (unsigned I = 0, N = Record.size(); I != N; ++I) {
+ if (unsigned GlobalID = getGlobalSubmoduleID(F, Record[I]))
+ ImportedModules.push_back(GlobalID);
+ }
+ }
+ break;
+ }
+
+ case LOCAL_REDECLARATIONS: {
+ F.RedeclarationChains.swap(Record);
+ break;
+ }
+
+ case LOCAL_REDECLARATIONS_MAP: {
+ if (F.LocalNumRedeclarationsInMap != 0) {
+ Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file");
+ return true;
+ }
+
+ F.LocalNumRedeclarationsInMap = Record[0];
+ F.RedeclarationsMap = (const LocalRedeclarationsInfo *)BlobStart;
+ break;
+ }
+
+ case MERGED_DECLARATIONS: {
+ for (unsigned Idx = 0; Idx < Record.size(); /* increment in loop */) {
+ GlobalDeclID CanonID = getGlobalDeclID(F, Record[Idx++]);
+ SmallVectorImpl<GlobalDeclID> &Decls = StoredMergedDecls[CanonID];
+ for (unsigned N = Record[Idx++]; N > 0; --N)
+ Decls.push_back(getGlobalDeclID(F, Record[Idx++]));
+ }
+ break;
+ }
+
+ case MACRO_OFFSET: {
+ if (F.LocalNumMacros != 0) {
+ Error("duplicate MACRO_OFFSET record in AST file");
+ return true;
+ }
+ F.MacroOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumMacros = Record[0];
+ unsigned LocalBaseMacroID = Record[1];
+ F.BaseMacroID = getTotalNumMacros();
+
+ if (F.LocalNumMacros > 0) {
+ // Introduce the global -> local mapping for macros within this module.
+ GlobalMacroMap.insert(std::make_pair(getTotalNumMacros() + 1, &F));
+
+ // Introduce the local -> global mapping for macros within this module.
+ F.MacroRemap.insertOrReplace(
+ std::make_pair(LocalBaseMacroID,
+ F.BaseMacroID - LocalBaseMacroID));
+
+ MacrosLoaded.resize(MacrosLoaded.size() + F.LocalNumMacros);
+ }
+ break;
+ }
+
+ case MACRO_UPDATES: {
+ for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
+ MacroID ID = getGlobalMacroID(F, Record[I++]);
+ if (I == N)
+ break;
+
+ SourceLocation UndefLoc = ReadSourceLocation(F, Record, I);
+ SubmoduleID SubmoduleID = getGlobalSubmoduleID(F, Record[I++]);;
+ MacroUpdate Update;
+ Update.UndefLoc = UndefLoc;
+ MacroUpdates[ID].push_back(std::make_pair(SubmoduleID, Update));
+ }
+ break;
+ }
+ }
+ }
+ Error("premature end of bitstream in AST file");
+ return true;
+}
+
+void ASTReader::makeNamesVisible(const HiddenNames &Names) {
+ for (unsigned I = 0, N = Names.size(); I != N; ++I) {
+ switch (Names[I].getKind()) {
+ case HiddenName::Declaration:
+ Names[I].getDecl()->Hidden = false;
+ break;
+
+ case HiddenName::MacroVisibility: {
+ std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
+ Macro.second->setHidden(!Macro.second->isPublic());
+ if (Macro.second->isDefined()) {
+ PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
+ }
+ break;
+ }
+
+ case HiddenName::MacroUndef: {
+ std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
+ if (Macro.second->isDefined()) {
+ Macro.second->setUndefLoc(Names[I].getMacroUndefLoc());
+ if (PPMutationListener *Listener = PP.getPPMutationListener())
+ Listener->UndefinedMacro(Macro.second);
+ PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
+ }
+ break;
+ }
+ }
+ }
+}
+
+void ASTReader::makeModuleVisible(Module *Mod,
+ Module::NameVisibilityKind NameVisibility) {
+ llvm::SmallPtrSet<Module *, 4> Visited;
+ llvm::SmallVector<Module *, 4> Stack;
+ Stack.push_back(Mod);
+ while (!Stack.empty()) {
+ Mod = Stack.back();
+ Stack.pop_back();
+
+ if (NameVisibility <= Mod->NameVisibility) {
+ // This module already has this level of visibility (or greater), so
+ // there is nothing more to do.
+ continue;
+ }
+
+ if (!Mod->isAvailable()) {
+ // Modules that aren't available cannot be made visible.
+ continue;
+ }
+
+ // Update the module's name visibility.
+ Mod->NameVisibility = NameVisibility;
+
+ // If we've already deserialized any names from this module,
+ // mark them as visible.
+ HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod);
+ if (Hidden != HiddenNamesMap.end()) {
+ makeNamesVisible(Hidden->second);
+ HiddenNamesMap.erase(Hidden);
+ }
+
+ // Push any non-explicit submodules onto the stack to be marked as
+ // visible.
+ for (Module::submodule_iterator Sub = Mod->submodule_begin(),
+ SubEnd = Mod->submodule_end();
+ Sub != SubEnd; ++Sub) {
+ if (!(*Sub)->IsExplicit && Visited.insert(*Sub))
+ Stack.push_back(*Sub);
+ }
+
+ // Push any exported modules onto the stack to be marked as visible.
+ bool AnyWildcard = false;
+ bool UnrestrictedWildcard = false;
+ llvm::SmallVector<Module *, 4> WildcardRestrictions;
+ for (unsigned I = 0, N = Mod->Exports.size(); I != N; ++I) {
+ Module *Exported = Mod->Exports[I].getPointer();
+ if (!Mod->Exports[I].getInt()) {
+ // Export a named module directly; no wildcards involved.
+ if (Visited.insert(Exported))
+ Stack.push_back(Exported);
+
+ continue;
+ }
+
+ // Wildcard export: export all of the imported modules that match
+ // the given pattern.
+ AnyWildcard = true;
+ if (UnrestrictedWildcard)
+ continue;
+
+ if (Module *Restriction = Mod->Exports[I].getPointer())
+ WildcardRestrictions.push_back(Restriction);
+ else {
+ WildcardRestrictions.clear();
+ UnrestrictedWildcard = true;
+ }
+ }
+
+ // If there were any wildcards, push any imported modules that were
+ // re-exported by the wildcard restriction.
+ if (!AnyWildcard)
+ continue;
+
+ for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) {
+ Module *Imported = Mod->Imports[I];
+ if (!Visited.insert(Imported))
+ continue;
+
+ bool Acceptable = UnrestrictedWildcard;
+ if (!Acceptable) {
+ // Check whether this module meets one of the restrictions.
+ for (unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) {
+ Module *Restriction = WildcardRestrictions[R];
+ if (Imported == Restriction || Imported->isSubModuleOf(Restriction)) {
+ Acceptable = true;
+ break;
+ }
+ }
+ }
+
+ if (!Acceptable)
+ continue;
+
+ Stack.push_back(Imported);
+ }
+ }
+}
+
+ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
+ ModuleKind Type,
+ SourceLocation ImportLoc,
+ unsigned ClientLoadCapabilities) {
+ // Bump the generation number.
+ unsigned PreviousGeneration = CurrentGeneration++;
+
+ unsigned NumModules = ModuleMgr.size();
+ llvm::SmallVector<ImportedModule, 4> Loaded;
+ switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc,
+ /*ImportedBy=*/0, Loaded,
+ ClientLoadCapabilities)) {
+ case Failure:
+ case OutOfDate:
+ case VersionMismatch:
+ case ConfigurationMismatch:
+ case HadErrors:
+ ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end());
+ return ReadResult;
+
+ case Success:
+ break;
+ }
+
+ // Here comes stuff that we only do once the entire chain is loaded.
+
+ // Load the AST blocks of all of the modules that we loaded.
+ for (llvm::SmallVectorImpl<ImportedModule>::iterator M = Loaded.begin(),
+ MEnd = Loaded.end();
+ M != MEnd; ++M) {
+ ModuleFile &F = *M->Mod;
+
+ // Read the AST block.
+ if (ReadASTBlock(F))
+ return Failure;
+
+ // Once read, set the ModuleFile bit base offset and update the size in
+ // bits of all files we've seen.
+ F.GlobalBitOffset = TotalModulesSizeInBits;
+ TotalModulesSizeInBits += F.SizeInBits;
+ GlobalBitOffsetsMap.insert(std::make_pair(F.GlobalBitOffset, &F));
+
+ // Preload SLocEntries.
+ for (unsigned I = 0, N = F.PreloadSLocEntries.size(); I != N; ++I) {
+ int Index = int(F.PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID;
+ // Load it through the SourceManager and don't call ReadSLocEntry()
+ // directly because the entry may have already been loaded in which case
+ // calling ReadSLocEntry() directly would trigger an assertion in
+ // SourceManager.
+ SourceMgr.getLoadedSLocEntryByID(Index);
+ }
+ }
+
+ // Setup the import locations.
+ for (llvm::SmallVectorImpl<ImportedModule>::iterator M = Loaded.begin(),
+ MEnd = Loaded.end();
+ M != MEnd; ++M) {
+ ModuleFile &F = *M->Mod;
+ if (!M->ImportedBy)
+ F.ImportLoc = M->ImportLoc;
+ else
+ F.ImportLoc = ReadSourceLocation(*M->ImportedBy,
+ M->ImportLoc.getRawEncoding());
+ }
+
+ // Mark all of the identifiers in the identifier table as being out of date,
+ // so that various accessors know to check the loaded modules when the
+ // identifier is used.
+ for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
+ IdEnd = PP.getIdentifierTable().end();
+ Id != IdEnd; ++Id)
+ Id->second->setOutOfDate(true);
+
+ // Resolve any unresolved module exports.
+ for (unsigned I = 0, N = UnresolvedModuleImportExports.size(); I != N; ++I) {
+ UnresolvedModuleImportExport &Unresolved = UnresolvedModuleImportExports[I];
+ SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,Unresolved.ID);
+ Module *ResolvedMod = getSubmodule(GlobalID);
+
+ if (Unresolved.IsImport) {
+ if (ResolvedMod)
+ Unresolved.Mod->Imports.push_back(ResolvedMod);
+ continue;
+ }
+
+ if (ResolvedMod || Unresolved.IsWildcard)
+ Unresolved.Mod->Exports.push_back(
+ Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard));
+ }
+ UnresolvedModuleImportExports.clear();
+
+ InitializeContext();
+
+ if (DeserializationListener)
+ DeserializationListener->ReaderInitialized(this);
+
+ ModuleFile &PrimaryModule = ModuleMgr.getPrimaryModule();
+ if (!PrimaryModule.OriginalSourceFileID.isInvalid()) {
+ PrimaryModule.OriginalSourceFileID
+ = FileID::get(PrimaryModule.SLocEntryBaseID
+ + PrimaryModule.OriginalSourceFileID.getOpaqueValue() - 1);
+
+ // If this AST file is a precompiled preamble, then set the
+ // preamble file ID of the source manager to the file source file
+ // from which the preamble was built.
+ if (Type == MK_Preamble) {
+ SourceMgr.setPreambleFileID(PrimaryModule.OriginalSourceFileID);
+ } else if (Type == MK_MainFile) {
+ SourceMgr.setMainFileID(PrimaryModule.OriginalSourceFileID);
+ }
+ }
+
+ // For any Objective-C class definitions we have already loaded, make sure
+ // that we load any additional categories.
+ for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) {
+ loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(),
+ ObjCClassesLoaded[I],
+ PreviousGeneration);
+ }
+
+ return Success;
+}
+
+ASTReader::ASTReadResult
+ASTReader::ReadASTCore(StringRef FileName,
+ ModuleKind Type,
+ SourceLocation ImportLoc,
+ ModuleFile *ImportedBy,
+ llvm::SmallVectorImpl<ImportedModule> &Loaded,
+ unsigned ClientLoadCapabilities) {
+ ModuleFile *M;
+ bool NewModule;
+ std::string ErrorStr;
+ llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportLoc,
+ ImportedBy, CurrentGeneration,
+ ErrorStr);
+
+ if (!M) {
+ // We couldn't load the module.
+ std::string Msg = "Unable to load module \"" + FileName.str() + "\": "
+ + ErrorStr;
+ Error(Msg);
+ return Failure;
+ }
+
+ if (!NewModule) {
+ // We've already loaded this module.
+ return Success;
+ }
+
+ // FIXME: This seems rather a hack. Should CurrentDir be part of the
+ // module?
+ if (FileName != "-") {
+ CurrentDir = llvm::sys::path::parent_path(FileName);
+ if (CurrentDir.empty()) CurrentDir = ".";
+ }
+
+ ModuleFile &F = *M;
+ llvm::BitstreamCursor &Stream = F.Stream;
+ Stream.init(F.StreamFile);
+ F.SizeInBits = F.Buffer->getBufferSize() * 8;
+
+ // Sniff for the signature.
+ if (Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'P' ||
+ Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'H') {
+ Diag(diag::err_not_a_pch_file) << FileName;
+ return Failure;
+ }
+
+ // This is used for compatibility with older PCH formats.
+ bool HaveReadControlBlock = false;
+
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+
+ if (Code != llvm::bitc::ENTER_SUBBLOCK) {
+ Error("invalid record at top-level of AST file");
+ return Failure;
+ }
+
+ unsigned BlockID = Stream.ReadSubBlockID();
+
+ // We only know the control subblock ID.
+ switch (BlockID) {
+ case llvm::bitc::BLOCKINFO_BLOCK_ID:
+ if (Stream.ReadBlockInfoBlock()) {
+ Error("malformed BlockInfoBlock in AST file");
+ return Failure;
+ }
+ break;
+ case CONTROL_BLOCK_ID:
+ HaveReadControlBlock = true;
+ switch (ReadControlBlock(F, Loaded, ClientLoadCapabilities)) {
+ case Success:
+ break;
+
+ case Failure: return Failure;
+ case OutOfDate: return OutOfDate;
+ case VersionMismatch: return VersionMismatch;
+ case ConfigurationMismatch: return ConfigurationMismatch;
+ case HadErrors: return HadErrors;
+ }
+ break;
+ case AST_BLOCK_ID:
+ if (!HaveReadControlBlock) {
+ if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
+ Diag(diag::warn_pch_version_too_old);
+ return VersionMismatch;
+ }
+
+ // Record that we've loaded this module.
+ Loaded.push_back(ImportedModule(M, ImportedBy, ImportLoc));
+ return Success;
+
+ default:
+ if (Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+ break;
+ }
+ }
+
+ return Success;
+}
+
+void ASTReader::InitializeContext() {
+ // If there's a listener, notify them that we "read" the translation unit.
+ if (DeserializationListener)
+ DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID,
+ Context.getTranslationUnitDecl());
+
+ // Make sure we load the declaration update records for the translation unit,
+ // if there are any.
+ loadDeclUpdateRecords(PREDEF_DECL_TRANSLATION_UNIT_ID,
+ Context.getTranslationUnitDecl());
+
+ // FIXME: Find a better way to deal with collisions between these
+ // built-in types. Right now, we just ignore the problem.
+
+ // Load the special types.
+ if (SpecialTypes.size() >= NumSpecialTypeIDs) {
+ if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING]) {
+ if (!Context.CFConstantStringTypeDecl)
+ Context.setCFConstantStringType(GetType(String));
+ }
+
+ if (unsigned File = SpecialTypes[SPECIAL_TYPE_FILE]) {
+ QualType FileType = GetType(File);
+ if (FileType.isNull()) {
+ Error("FILE type is NULL");
+ return;
+ }
+
+ if (!Context.FILEDecl) {
+ if (const TypedefType *Typedef = FileType->getAs<TypedefType>())
+ Context.setFILEDecl(Typedef->getDecl());
+ else {
+ const TagType *Tag = FileType->getAs<TagType>();
+ if (!Tag) {
+ Error("Invalid FILE type in AST file");
+ return;
+ }
+ Context.setFILEDecl(Tag->getDecl());
+ }
+ }
+ }
+
+ if (unsigned Jmp_buf = SpecialTypes[SPECIAL_TYPE_JMP_BUF]) {
+ QualType Jmp_bufType = GetType(Jmp_buf);
+ if (Jmp_bufType.isNull()) {
+ Error("jmp_buf type is NULL");
+ return;
+ }
+
+ if (!Context.jmp_bufDecl) {
+ if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>())
+ Context.setjmp_bufDecl(Typedef->getDecl());
+ else {
+ const TagType *Tag = Jmp_bufType->getAs<TagType>();
+ if (!Tag) {
+ Error("Invalid jmp_buf type in AST file");
+ return;
+ }
+ Context.setjmp_bufDecl(Tag->getDecl());
+ }
+ }
+ }
+
+ if (unsigned Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_SIGJMP_BUF]) {
+ QualType Sigjmp_bufType = GetType(Sigjmp_buf);
+ if (Sigjmp_bufType.isNull()) {
+ Error("sigjmp_buf type is NULL");
+ return;
+ }
+
+ if (!Context.sigjmp_bufDecl) {
+ if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>())
+ Context.setsigjmp_bufDecl(Typedef->getDecl());
+ else {
+ const TagType *Tag = Sigjmp_bufType->getAs<TagType>();
+ assert(Tag && "Invalid sigjmp_buf type in AST file");
+ Context.setsigjmp_bufDecl(Tag->getDecl());
+ }
+ }
+ }
+
+ if (unsigned ObjCIdRedef
+ = SpecialTypes[SPECIAL_TYPE_OBJC_ID_REDEFINITION]) {
+ if (Context.ObjCIdRedefinitionType.isNull())
+ Context.ObjCIdRedefinitionType = GetType(ObjCIdRedef);
+ }
+
+ if (unsigned ObjCClassRedef
+ = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) {
+ if (Context.ObjCClassRedefinitionType.isNull())
+ Context.ObjCClassRedefinitionType = GetType(ObjCClassRedef);
+ }
+
+ if (unsigned ObjCSelRedef
+ = SpecialTypes[SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) {
+ if (Context.ObjCSelRedefinitionType.isNull())
+ Context.ObjCSelRedefinitionType = GetType(ObjCSelRedef);
+ }
+
+ if (unsigned Ucontext_t = SpecialTypes[SPECIAL_TYPE_UCONTEXT_T]) {
+ QualType Ucontext_tType = GetType(Ucontext_t);
+ if (Ucontext_tType.isNull()) {
+ Error("ucontext_t type is NULL");
+ return;
+ }
+
+ if (!Context.ucontext_tDecl) {
+ if (const TypedefType *Typedef = Ucontext_tType->getAs<TypedefType>())
+ Context.setucontext_tDecl(Typedef->getDecl());
+ else {
+ const TagType *Tag = Ucontext_tType->getAs<TagType>();
+ assert(Tag && "Invalid ucontext_t type in AST file");
+ Context.setucontext_tDecl(Tag->getDecl());
+ }
+ }
+ }
+ }
+
+ ReadPragmaDiagnosticMappings(Context.getDiagnostics());
+
+ // If there were any CUDA special declarations, deserialize them.
+ if (!CUDASpecialDeclRefs.empty()) {
+ assert(CUDASpecialDeclRefs.size() == 1 && "More decl refs than expected!");
+ Context.setcudaConfigureCallDecl(
+ cast<FunctionDecl>(GetDecl(CUDASpecialDeclRefs[0])));
+ }
+
+ // Re-export any modules that were imported by a non-module AST file.
+ for (unsigned I = 0, N = ImportedModules.size(); I != N; ++I) {
+ if (Module *Imported = getSubmodule(ImportedModules[I]))
+ makeModuleVisible(Imported, Module::AllVisible);
+ }
+ ImportedModules.clear();
+}
+
+void ASTReader::finalizeForWriting() {
+ for (HiddenNamesMapType::iterator Hidden = HiddenNamesMap.begin(),
+ HiddenEnd = HiddenNamesMap.end();
+ Hidden != HiddenEnd; ++Hidden) {
+ makeNamesVisible(Hidden->second);
+ }
+ HiddenNamesMap.clear();
+}
+
+/// \brief Retrieve the name of the original source file name
+/// directly from the AST file, without actually loading the AST
+/// file.
+std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
+ FileManager &FileMgr,
+ DiagnosticsEngine &Diags) {
+ // Open the AST file.
+ std::string ErrStr;
+ OwningPtr<llvm::MemoryBuffer> Buffer;
+ Buffer.reset(FileMgr.getBufferForFile(ASTFileName, &ErrStr));
+ if (!Buffer) {
+ Diags.Report(diag::err_fe_unable_to_read_pch_file) << ASTFileName << ErrStr;
+ return std::string();
+ }
+
+ // Initialize the stream
+ llvm::BitstreamReader StreamFile;
+ llvm::BitstreamCursor Stream;
+ StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
+ (const unsigned char *)Buffer->getBufferEnd());
+ Stream.init(StreamFile);
+
+ // Sniff for the signature.
+ if (Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'P' ||
+ Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'H') {
+ Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName;
+ return std::string();
+ }
+
+ RecordData Record;
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ unsigned BlockID = Stream.ReadSubBlockID();
+
+ // We only know the AST subblock ID.
+ switch (BlockID) {
+ case CONTROL_BLOCK_ID:
+ if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
+ Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
+ return std::string();
+ }
+ break;
+
+ default:
+ if (Stream.SkipBlock()) {
+ Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
+ return std::string();
+ }
+ break;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (Stream.ReadBlockEnd()) {
+ Diags.Report(diag::err_fe_pch_error_at_end_block) << ASTFileName;
+ return std::string();
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ Record.clear();
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen) == ORIGINAL_FILE)
+ return std::string(BlobStart, BlobLen);
+ }
+
+ return std::string();
+}
+
+namespace {
+ class SimplePCHValidator : public ASTReaderListener {
+ const LangOptions &ExistingLangOpts;
+ const TargetOptions &ExistingTargetOpts;
+ const PreprocessorOptions &ExistingPPOpts;
+ FileManager &FileMgr;
+
+ public:
+ SimplePCHValidator(const LangOptions &ExistingLangOpts,
+ const TargetOptions &ExistingTargetOpts,
+ const PreprocessorOptions &ExistingPPOpts,
+ FileManager &FileMgr)
+ : ExistingLangOpts(ExistingLangOpts),
+ ExistingTargetOpts(ExistingTargetOpts),
+ ExistingPPOpts(ExistingPPOpts),
+ FileMgr(FileMgr)
+ {
+ }
+
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
+ bool Complain) {
+ return checkLanguageOptions(ExistingLangOpts, LangOpts, 0);
+ }
+ virtual bool ReadTargetOptions(const TargetOptions &TargetOpts,
+ bool Complain) {
+ return checkTargetOptions(ExistingTargetOpts, TargetOpts, 0);
+ }
+ virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
+ bool Complain,
+ std::string &SuggestedPredefines) {
+ return checkPreprocessorOptions(ExistingPPOpts, PPOpts, 0, FileMgr,
+ SuggestedPredefines);
+ }
+ };
+}
+
+bool ASTReader::readASTFileControlBlock(StringRef Filename,
+ FileManager &FileMgr,
+ ASTReaderListener &Listener) {
+ // Open the AST file.
+ std::string ErrStr;
+ OwningPtr<llvm::MemoryBuffer> Buffer;
+ Buffer.reset(FileMgr.getBufferForFile(Filename, &ErrStr));
+ if (!Buffer) {
+ return true;
+ }
+
+ // Initialize the stream
+ llvm::BitstreamReader StreamFile;
+ llvm::BitstreamCursor Stream;
+ StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
+ (const unsigned char *)Buffer->getBufferEnd());
+ Stream.init(StreamFile);
+
+ // Sniff for the signature.
+ if (Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'P' ||
+ Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'H') {
+ return true;
+ }
+
+ RecordData Record;
+ bool InControlBlock = false;
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ unsigned BlockID = Stream.ReadSubBlockID();
+
+ // We only know the control subblock ID.
+ switch (BlockID) {
+ case CONTROL_BLOCK_ID:
+ if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
+ return true;
+ } else {
+ InControlBlock = true;
+ }
+ break;
+
+ default:
+ if (Stream.SkipBlock())
+ return true;
+ break;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (Stream.ReadBlockEnd()) {
+ return true;
+ }
+
+ InControlBlock = false;
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ Record.clear();
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+ if (InControlBlock) {
+ switch ((ControlRecordTypes)RecCode) {
+ case METADATA: {
+ if (Record[0] != VERSION_MAJOR) {
+ return true;
+ }
+
+ const std::string &CurBranch = getClangFullRepositoryVersion();
+ StringRef ASTBranch(BlobStart, BlobLen);
+ if (StringRef(CurBranch) != ASTBranch)
+ return true;
+
+ break;
+ }
+ case LANGUAGE_OPTIONS:
+ if (ParseLanguageOptions(Record, false, Listener))
+ return true;
+ break;
+
+ case TARGET_OPTIONS:
+ if (ParseTargetOptions(Record, false, Listener))
+ return true;
+ break;
+
+ case DIAGNOSTIC_OPTIONS:
+ if (ParseDiagnosticOptions(Record, false, Listener))
+ return true;
+ break;
+
+ case FILE_SYSTEM_OPTIONS:
+ if (ParseFileSystemOptions(Record, false, Listener))
+ return true;
+ break;
+
+ case HEADER_SEARCH_OPTIONS:
+ if (ParseHeaderSearchOptions(Record, false, Listener))
+ return true;
+ break;
+
+ case PREPROCESSOR_OPTIONS: {
+ std::string IgnoredSuggestedPredefines;
+ if (ParsePreprocessorOptions(Record, false, Listener,
+ IgnoredSuggestedPredefines))
+ return true;
+ break;
+ }
+
+ default:
+ // No other validation to perform.
+ break;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+bool ASTReader::isAcceptableASTFile(StringRef Filename,
+ FileManager &FileMgr,
+ const LangOptions &LangOpts,
+ const TargetOptions &TargetOpts,
+ const PreprocessorOptions &PPOpts) {
+ SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, FileMgr);
+ return !readASTFileControlBlock(Filename, FileMgr, validator);
+}
+
+bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
+ // Enter the submodule block.
+ if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) {
+ Error("malformed submodule block record in AST file");
+ return true;
+ }
+
+ ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
+ bool First = true;
+ Module *CurrentModule = 0;
+ RecordData Record;
+ while (true) {
+ unsigned Code = F.Stream.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (F.Stream.ReadBlockEnd()) {
+ Error("error at end of submodule block in AST file");
+ return true;
+ }
+ return false;
+ }
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ F.Stream.ReadSubBlockID();
+ if (F.Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return true;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ F.Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read a record.
+ const char *BlobStart;
+ unsigned BlobLen;
+ Record.clear();
+ switch (F.Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+ default: // Default behavior: ignore.
+ break;
+
+ case SUBMODULE_DEFINITION: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return true;
+ }
+
+ if (Record.size() < 7) {
+ Error("malformed module definition");
+ return true;
+ }
+
+ StringRef Name(BlobStart, BlobLen);
+ SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[0]);
+ SubmoduleID Parent = getGlobalSubmoduleID(F, Record[1]);
+ bool IsFramework = Record[2];
+ bool IsExplicit = Record[3];
+ bool IsSystem = Record[4];
+ bool InferSubmodules = Record[5];
+ bool InferExplicitSubmodules = Record[6];
+ bool InferExportWildcard = Record[7];
+
+ Module *ParentModule = 0;
+ if (Parent)
+ ParentModule = getSubmodule(Parent);
+
+ // Retrieve this (sub)module from the module map, creating it if
+ // necessary.
+ CurrentModule = ModMap.findOrCreateModule(Name, ParentModule,
+ IsFramework,
+ IsExplicit).first;
+ SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS;
+ if (GlobalIndex >= SubmodulesLoaded.size() ||
+ SubmodulesLoaded[GlobalIndex]) {
+ Error("too many submodules");
+ return true;
+ }
+
+ CurrentModule->setASTFile(F.File);
+ CurrentModule->IsFromModuleFile = true;
+ CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
+ CurrentModule->InferSubmodules = InferSubmodules;
+ CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
+ CurrentModule->InferExportWildcard = InferExportWildcard;
+ if (DeserializationListener)
+ DeserializationListener->ModuleRead(GlobalID, CurrentModule);
+
+ SubmodulesLoaded[GlobalIndex] = CurrentModule;
+ break;
+ }
+
+ case SUBMODULE_UMBRELLA_HEADER: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return true;
+ }
+
+ if (!CurrentModule)
+ break;
+
+ StringRef FileName(BlobStart, BlobLen);
+ if (const FileEntry *Umbrella = PP.getFileManager().getFile(FileName)) {
+ if (!CurrentModule->getUmbrellaHeader())
+ ModMap.setUmbrellaHeader(CurrentModule, Umbrella);
+ else if (CurrentModule->getUmbrellaHeader() != Umbrella) {
+ Error("mismatched umbrella headers in submodule");
+ return true;
+ }
+ }
+ break;
+ }
+
+ case SUBMODULE_HEADER: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return true;
+ }
+
+ if (!CurrentModule)
+ break;
+
+ // FIXME: Be more lazy about this!
+ StringRef FileName(BlobStart, BlobLen);
+ if (const FileEntry *File = PP.getFileManager().getFile(FileName)) {
+ if (std::find(CurrentModule->Headers.begin(),
+ CurrentModule->Headers.end(),
+ File) == CurrentModule->Headers.end())
+ ModMap.addHeader(CurrentModule, File, false);
+ }
+ break;
+ }
+
+ case SUBMODULE_EXCLUDED_HEADER: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return true;
+ }
+
+ if (!CurrentModule)
+ break;
+
+ // FIXME: Be more lazy about this!
+ StringRef FileName(BlobStart, BlobLen);
+ if (const FileEntry *File = PP.getFileManager().getFile(FileName)) {
+ if (std::find(CurrentModule->Headers.begin(),
+ CurrentModule->Headers.end(),
+ File) == CurrentModule->Headers.end())
+ ModMap.addHeader(CurrentModule, File, true);
+ }
+ break;
+ }
+
+ case SUBMODULE_TOPHEADER: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return true;
+ }
+
+ if (!CurrentModule)
+ break;
+
+ // FIXME: Be more lazy about this!
+ StringRef FileName(BlobStart, BlobLen);
+ if (const FileEntry *File = PP.getFileManager().getFile(FileName))
+ CurrentModule->TopHeaders.insert(File);
+ break;
+ }
+
+ case SUBMODULE_UMBRELLA_DIR: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return true;
+ }
+
+ if (!CurrentModule)
+ break;
+
+ StringRef DirName(BlobStart, BlobLen);
+ if (const DirectoryEntry *Umbrella
+ = PP.getFileManager().getDirectory(DirName)) {
+ if (!CurrentModule->getUmbrellaDir())
+ ModMap.setUmbrellaDir(CurrentModule, Umbrella);
+ else if (CurrentModule->getUmbrellaDir() != Umbrella) {
+ Error("mismatched umbrella directories in submodule");
+ return true;
+ }
+ }
+ break;
+ }
+
+ case SUBMODULE_METADATA: {
+ if (!First) {
+ Error("submodule metadata record not at beginning of block");
+ return true;
+ }
+ First = false;
+
+ F.BaseSubmoduleID = getTotalNumSubmodules();
+ F.LocalNumSubmodules = Record[0];
+ unsigned LocalBaseSubmoduleID = Record[1];
+ if (F.LocalNumSubmodules > 0) {
+ // Introduce the global -> local mapping for submodules within this
+ // module.
+ GlobalSubmoduleMap.insert(std::make_pair(getTotalNumSubmodules()+1,&F));
+
+ // Introduce the local -> global mapping for submodules within this
+ // module.
+ F.SubmoduleRemap.insertOrReplace(
+ std::make_pair(LocalBaseSubmoduleID,
+ F.BaseSubmoduleID - LocalBaseSubmoduleID));
+
+ SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules);
+ }
+ break;
+ }
+
+ case SUBMODULE_IMPORTS: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return true;
+ }
+
+ if (!CurrentModule)
+ break;
+
+ for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {
+ UnresolvedModuleImportExport Unresolved;
+ Unresolved.File = &F;
+ Unresolved.Mod = CurrentModule;
+ Unresolved.ID = Record[Idx];
+ Unresolved.IsImport = true;
+ Unresolved.IsWildcard = false;
+ UnresolvedModuleImportExports.push_back(Unresolved);
+ }
+ break;
+ }
+
+ case SUBMODULE_EXPORTS: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return true;
+ }
+
+ if (!CurrentModule)
+ break;
+
+ for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {
+ UnresolvedModuleImportExport Unresolved;
+ Unresolved.File = &F;
+ Unresolved.Mod = CurrentModule;
+ Unresolved.ID = Record[Idx];
+ Unresolved.IsImport = false;
+ Unresolved.IsWildcard = Record[Idx + 1];
+ UnresolvedModuleImportExports.push_back(Unresolved);
+ }
+
+ // Once we've loaded the set of exports, there's no reason to keep
+ // the parsed, unresolved exports around.
+ CurrentModule->UnresolvedExports.clear();
+ break;
+ }
+ case SUBMODULE_REQUIRES: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return true;
+ }
+
+ if (!CurrentModule)
+ break;
+
+ CurrentModule->addRequirement(StringRef(BlobStart, BlobLen),
+ Context.getLangOpts(),
+ Context.getTargetInfo());
+ break;
+ }
+ }
+ }
+}
+
+/// \brief Parse the record that corresponds to a LangOptions data
+/// structure.
+///
+/// This routine parses the language options from the AST file and then gives
+/// them to the AST listener if one is set.
+///
+/// \returns true if the listener deems the file unacceptable, false otherwise.
+bool ASTReader::ParseLanguageOptions(const RecordData &Record,
+ bool Complain,
+ ASTReaderListener &Listener) {
+ LangOptions LangOpts;
+ unsigned Idx = 0;
+#define LANGOPT(Name, Bits, Default, Description) \
+ LangOpts.Name = Record[Idx++];
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+ LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++]));
+#include "clang/Basic/LangOptions.def"
+
+ ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++];
+ VersionTuple runtimeVersion = ReadVersionTuple(Record, Idx);
+ LangOpts.ObjCRuntime = ObjCRuntime(runtimeKind, runtimeVersion);
+
+ unsigned Length = Record[Idx++];
+ LangOpts.CurrentModule.assign(Record.begin() + Idx,
+ Record.begin() + Idx + Length);
+ return Listener.ReadLanguageOptions(LangOpts, Complain);
+}
+
+bool ASTReader::ParseTargetOptions(const RecordData &Record,
+ bool Complain,
+ ASTReaderListener &Listener) {
+ unsigned Idx = 0;
+ TargetOptions TargetOpts;
+ TargetOpts.Triple = ReadString(Record, Idx);
+ TargetOpts.CPU = ReadString(Record, Idx);
+ TargetOpts.ABI = ReadString(Record, Idx);
+ TargetOpts.CXXABI = ReadString(Record, Idx);
+ TargetOpts.LinkerVersion = ReadString(Record, Idx);
+ for (unsigned N = Record[Idx++]; N; --N) {
+ TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx));
+ }
+ for (unsigned N = Record[Idx++]; N; --N) {
+ TargetOpts.Features.push_back(ReadString(Record, Idx));
+ }
+
+ return Listener.ReadTargetOptions(TargetOpts, Complain);
+}
+
+bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener) {
+ DiagnosticOptions DiagOpts;
+ unsigned Idx = 0;
+#define DIAGOPT(Name, Bits, Default) DiagOpts.Name = Record[Idx++];
+#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
+ DiagOpts.set##Name(static_cast<Type>(Record[Idx++]));
+#include "clang/Basic/DiagnosticOptions.def"
+
+ for (unsigned N = Record[Idx++]; N; --N) {
+ DiagOpts.Warnings.push_back(ReadString(Record, Idx));
+ }
+
+ return Listener.ReadDiagnosticOptions(DiagOpts, Complain);
+}
+
+bool ASTReader::ParseFileSystemOptions(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener) {
+ FileSystemOptions FSOpts;
+ unsigned Idx = 0;
+ FSOpts.WorkingDir = ReadString(Record, Idx);
+ return Listener.ReadFileSystemOptions(FSOpts, Complain);
+}
+
+bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
+ bool Complain,
+ ASTReaderListener &Listener) {
+ HeaderSearchOptions HSOpts;
+ unsigned Idx = 0;
+ HSOpts.Sysroot = ReadString(Record, Idx);
+
+ // Include entries.
+ for (unsigned N = Record[Idx++]; N; --N) {
+ std::string Path = ReadString(Record, Idx);
+ frontend::IncludeDirGroup Group
+ = static_cast<frontend::IncludeDirGroup>(Record[Idx++]);
+ bool IsUserSupplied = Record[Idx++];
+ bool IsFramework = Record[Idx++];
+ bool IgnoreSysRoot = Record[Idx++];
+ bool IsInternal = Record[Idx++];
+ bool ImplicitExternC = Record[Idx++];
+ HSOpts.UserEntries.push_back(
+ HeaderSearchOptions::Entry(Path, Group, IsUserSupplied, IsFramework,
+ IgnoreSysRoot, IsInternal, ImplicitExternC));
+ }
+
+ // System header prefixes.
+ for (unsigned N = Record[Idx++]; N; --N) {
+ std::string Prefix = ReadString(Record, Idx);
+ bool IsSystemHeader = Record[Idx++];
+ HSOpts.SystemHeaderPrefixes.push_back(
+ HeaderSearchOptions::SystemHeaderPrefix(Prefix, IsSystemHeader));
+ }
+
+ HSOpts.ResourceDir = ReadString(Record, Idx);
+ HSOpts.ModuleCachePath = ReadString(Record, Idx);
+ HSOpts.DisableModuleHash = Record[Idx++];
+ HSOpts.UseBuiltinIncludes = Record[Idx++];
+ HSOpts.UseStandardSystemIncludes = Record[Idx++];
+ HSOpts.UseStandardCXXIncludes = Record[Idx++];
+ HSOpts.UseLibcxx = Record[Idx++];
+
+ return Listener.ReadHeaderSearchOptions(HSOpts, Complain);
+}
+
+bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
+ bool Complain,
+ ASTReaderListener &Listener,
+ std::string &SuggestedPredefines) {
+ PreprocessorOptions PPOpts;
+ unsigned Idx = 0;
+
+ // Macro definitions/undefs
+ for (unsigned N = Record[Idx++]; N; --N) {
+ std::string Macro = ReadString(Record, Idx);
+ bool IsUndef = Record[Idx++];
+ PPOpts.Macros.push_back(std::make_pair(Macro, IsUndef));
+ }
+
+ // Includes
+ for (unsigned N = Record[Idx++]; N; --N) {
+ PPOpts.Includes.push_back(ReadString(Record, Idx));
+ }
+
+ // Macro Includes
+ for (unsigned N = Record[Idx++]; N; --N) {
+ PPOpts.MacroIncludes.push_back(ReadString(Record, Idx));
+ }
+
+ PPOpts.UsePredefines = Record[Idx++];
+ PPOpts.ImplicitPCHInclude = ReadString(Record, Idx);
+ PPOpts.ImplicitPTHInclude = ReadString(Record, Idx);
+ PPOpts.ObjCXXARCStandardLibrary =
+ static_cast<ObjCXXARCStandardLibraryKind>(Record[Idx++]);
+ SuggestedPredefines.clear();
+ return Listener.ReadPreprocessorOptions(PPOpts, Complain,
+ SuggestedPredefines);
+}
+
+std::pair<ModuleFile *, unsigned>
+ASTReader::getModulePreprocessedEntity(unsigned GlobalIndex) {
+ GlobalPreprocessedEntityMapType::iterator
+ I = GlobalPreprocessedEntityMap.find(GlobalIndex);
+ assert(I != GlobalPreprocessedEntityMap.end() &&
+ "Corrupted global preprocessed entity map");
+ ModuleFile *M = I->second;
+ unsigned LocalIndex = GlobalIndex - M->BasePreprocessedEntityID;
+ return std::make_pair(M, LocalIndex);
+}
+
+std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
+ASTReader::getModulePreprocessedEntities(ModuleFile &Mod) const {
+ if (PreprocessingRecord *PPRec = PP.getPreprocessingRecord())
+ return PPRec->getIteratorsForLoadedRange(Mod.BasePreprocessedEntityID,
+ Mod.NumPreprocessedEntities);
+
+ return std::make_pair(PreprocessingRecord::iterator(),
+ PreprocessingRecord::iterator());
+}
+
+std::pair<ASTReader::ModuleDeclIterator, ASTReader::ModuleDeclIterator>
+ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) {
+ return std::make_pair(ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls),
+ ModuleDeclIterator(this, &Mod,
+ Mod.FileSortedDecls + Mod.NumFileSortedDecls));
+}
+
+PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
+ PreprocessedEntityID PPID = Index+1;
+ std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index);
+ ModuleFile &M = *PPInfo.first;
+ unsigned LocalIndex = PPInfo.second;
+ const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex];
+
+ SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor);
+ M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset);
+
+ unsigned Code = M.PreprocessorDetailCursor.ReadCode();
+ switch (Code) {
+ case llvm::bitc::END_BLOCK:
+ return 0;
+
+ case llvm::bitc::ENTER_SUBBLOCK:
+ Error("unexpected subblock record in preprocessor detail block");
+ return 0;
+
+ case llvm::bitc::DEFINE_ABBREV:
+ Error("unexpected abbrevation record in preprocessor detail block");
+ return 0;
+
+ default:
+ break;
+ }
+
+ if (!PP.getPreprocessingRecord()) {
+ Error("no preprocessing record");
+ return 0;
+ }
+
+ // Read the record.
+ SourceRange Range(ReadSourceLocation(M, PPOffs.Begin),
+ ReadSourceLocation(M, PPOffs.End));
+ PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ RecordData Record;
+ PreprocessorDetailRecordTypes RecType =
+ (PreprocessorDetailRecordTypes)M.PreprocessorDetailCursor.ReadRecord(
+ Code, Record, BlobStart, BlobLen);
+ switch (RecType) {
+ case PPD_MACRO_EXPANSION: {
+ bool isBuiltin = Record[0];
+ IdentifierInfo *Name = 0;
+ MacroDefinition *Def = 0;
+ if (isBuiltin)
+ Name = getLocalIdentifier(M, Record[1]);
+ else {
+ PreprocessedEntityID
+ GlobalID = getGlobalPreprocessedEntityID(M, Record[1]);
+ Def =cast<MacroDefinition>(PPRec.getLoadedPreprocessedEntity(GlobalID-1));
+ }
+
+ MacroExpansion *ME;
+ if (isBuiltin)
+ ME = new (PPRec) MacroExpansion(Name, Range);
+ else
+ ME = new (PPRec) MacroExpansion(Def, Range);
+
+ return ME;
+ }
+
+ case PPD_MACRO_DEFINITION: {
+ // Decode the identifier info and then check again; if the macro is
+ // still defined and associated with the identifier,
+ IdentifierInfo *II = getLocalIdentifier(M, Record[0]);
+ MacroDefinition *MD
+ = new (PPRec) MacroDefinition(II, Range);
+
+ if (DeserializationListener)
+ DeserializationListener->MacroDefinitionRead(PPID, MD);
+
+ return MD;
+ }
+
+ case PPD_INCLUSION_DIRECTIVE: {
+ const char *FullFileNameStart = BlobStart + Record[0];
+ StringRef FullFileName(FullFileNameStart, BlobLen - Record[0]);
+ const FileEntry *File = 0;
+ if (!FullFileName.empty())
+ File = PP.getFileManager().getFile(FullFileName);
+
+ // FIXME: Stable encoding
+ InclusionDirective::InclusionKind Kind
+ = static_cast<InclusionDirective::InclusionKind>(Record[2]);
+ InclusionDirective *ID
+ = new (PPRec) InclusionDirective(PPRec, Kind,
+ StringRef(BlobStart, Record[0]),
+ Record[1], Record[3],
+ File,
+ Range);
+ return ID;
+ }
+ }
+
+ llvm_unreachable("Invalid PreprocessorDetailRecordTypes");
+}
+
+/// \brief \arg SLocMapI points at a chunk of a module that contains no
+/// preprocessed entities or the entities it contains are not the ones we are
+/// looking for. Find the next module that contains entities and return the ID
+/// of the first entry.
+PreprocessedEntityID ASTReader::findNextPreprocessedEntity(
+ GlobalSLocOffsetMapType::const_iterator SLocMapI) const {
+ ++SLocMapI;
+ for (GlobalSLocOffsetMapType::const_iterator
+ EndI = GlobalSLocOffsetMap.end(); SLocMapI != EndI; ++SLocMapI) {
+ ModuleFile &M = *SLocMapI->second;
+ if (M.NumPreprocessedEntities)
+ return M.BasePreprocessedEntityID;
+ }
+
+ return getTotalNumPreprocessedEntities();
+}
+
+namespace {
+
+template <unsigned PPEntityOffset::*PPLoc>
+struct PPEntityComp {
+ const ASTReader &Reader;
+ ModuleFile &M;
+
+ PPEntityComp(const ASTReader &Reader, ModuleFile &M) : Reader(Reader), M(M) { }
+
+ bool operator()(const PPEntityOffset &L, const PPEntityOffset &R) const {
+ SourceLocation LHS = getLoc(L);
+ SourceLocation RHS = getLoc(R);
+ return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+ }
+
+ bool operator()(const PPEntityOffset &L, SourceLocation RHS) const {
+ SourceLocation LHS = getLoc(L);
+ return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+ }
+
+ bool operator()(SourceLocation LHS, const PPEntityOffset &R) const {
+ SourceLocation RHS = getLoc(R);
+ return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+ }
+
+ SourceLocation getLoc(const PPEntityOffset &PPE) const {
+ return Reader.ReadSourceLocation(M, PPE.*PPLoc);
+ }
+};
+
+}
+
+/// \brief Returns the first preprocessed entity ID that ends after \arg BLoc.
+PreprocessedEntityID
+ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const {
+ if (SourceMgr.isLocalSourceLocation(BLoc))
+ return getTotalNumPreprocessedEntities();
+
+ GlobalSLocOffsetMapType::const_iterator
+ SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -
+ BLoc.getOffset());
+ assert(SLocMapI != GlobalSLocOffsetMap.end() &&
+ "Corrupted global sloc offset map");
+
+ if (SLocMapI->second->NumPreprocessedEntities == 0)
+ return findNextPreprocessedEntity(SLocMapI);
+
+ ModuleFile &M = *SLocMapI->second;
+ typedef const PPEntityOffset *pp_iterator;
+ pp_iterator pp_begin = M.PreprocessedEntityOffsets;
+ pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities;
+
+ size_t Count = M.NumPreprocessedEntities;
+ size_t Half;
+ pp_iterator First = pp_begin;
+ pp_iterator PPI;
+
+ // Do a binary search manually instead of using std::lower_bound because
+ // The end locations of entities may be unordered (when a macro expansion
+ // is inside another macro argument), but for this case it is not important
+ // whether we get the first macro expansion or its containing macro.
+ while (Count > 0) {
+ Half = Count/2;
+ PPI = First;
+ std::advance(PPI, Half);
+ if (SourceMgr.isBeforeInTranslationUnit(ReadSourceLocation(M, PPI->End),
+ BLoc)){
+ First = PPI;
+ ++First;
+ Count = Count - Half - 1;
+ } else
+ Count = Half;
+ }
+
+ if (PPI == pp_end)
+ return findNextPreprocessedEntity(SLocMapI);
+
+ return M.BasePreprocessedEntityID + (PPI - pp_begin);
+}
+
+/// \brief Returns the first preprocessed entity ID that begins after \arg ELoc.
+PreprocessedEntityID
+ASTReader::findEndPreprocessedEntity(SourceLocation ELoc) const {
+ if (SourceMgr.isLocalSourceLocation(ELoc))
+ return getTotalNumPreprocessedEntities();
+
+ GlobalSLocOffsetMapType::const_iterator
+ SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -
+ ELoc.getOffset());
+ assert(SLocMapI != GlobalSLocOffsetMap.end() &&
+ "Corrupted global sloc offset map");
+
+ if (SLocMapI->second->NumPreprocessedEntities == 0)
+ return findNextPreprocessedEntity(SLocMapI);
+
+ ModuleFile &M = *SLocMapI->second;
+ typedef const PPEntityOffset *pp_iterator;
+ pp_iterator pp_begin = M.PreprocessedEntityOffsets;
+ pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities;
+ pp_iterator PPI =
+ std::upper_bound(pp_begin, pp_end, ELoc,
+ PPEntityComp<&PPEntityOffset::Begin>(*this, M));
+
+ if (PPI == pp_end)
+ return findNextPreprocessedEntity(SLocMapI);
+
+ return M.BasePreprocessedEntityID + (PPI - pp_begin);
+}
+
+/// \brief Returns a pair of [Begin, End) indices of preallocated
+/// preprocessed entities that \arg Range encompasses.
+std::pair<unsigned, unsigned>
+ ASTReader::findPreprocessedEntitiesInRange(SourceRange Range) {
+ if (Range.isInvalid())
+ return std::make_pair(0,0);
+ assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
+
+ PreprocessedEntityID BeginID = findBeginPreprocessedEntity(Range.getBegin());
+ PreprocessedEntityID EndID = findEndPreprocessedEntity(Range.getEnd());
+ return std::make_pair(BeginID, EndID);
+}
+
+/// \brief Optionally returns true or false if the preallocated preprocessed
+/// entity with index \arg Index came from file \arg FID.
+llvm::Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index,
+ FileID FID) {
+ if (FID.isInvalid())
+ return false;
+
+ std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index);
+ ModuleFile &M = *PPInfo.first;
+ unsigned LocalIndex = PPInfo.second;
+ const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex];
+
+ SourceLocation Loc = ReadSourceLocation(M, PPOffs.Begin);
+ if (Loc.isInvalid())
+ return false;
+
+ if (SourceMgr.isInFileID(SourceMgr.getFileLoc(Loc), FID))
+ return true;
+ else
+ return false;
+}
+
+namespace {
+ /// \brief Visitor used to search for information about a header file.
+ class HeaderFileInfoVisitor {
+ ASTReader &Reader;
+ const FileEntry *FE;
+
+ llvm::Optional<HeaderFileInfo> HFI;
+
+ public:
+ HeaderFileInfoVisitor(ASTReader &Reader, const FileEntry *FE)
+ : Reader(Reader), FE(FE) { }
+
+ static bool visit(ModuleFile &M, void *UserData) {
+ HeaderFileInfoVisitor *This
+ = static_cast<HeaderFileInfoVisitor *>(UserData);
+
+ HeaderFileInfoTrait Trait(This->Reader, M,
+ &This->Reader.getPreprocessor().getHeaderSearchInfo(),
+ M.HeaderFileFrameworkStrings,
+ This->FE->getName());
+
+ HeaderFileInfoLookupTable *Table
+ = static_cast<HeaderFileInfoLookupTable *>(M.HeaderFileInfoTable);
+ if (!Table)
+ return false;
+
+ // Look in the on-disk hash table for an entry for this file name.
+ HeaderFileInfoLookupTable::iterator Pos = Table->find(This->FE->getName(),
+ &Trait);
+ if (Pos == Table->end())
+ return false;
+
+ This->HFI = *Pos;
+ return true;
+ }
+
+ llvm::Optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; }
+ };
+}
+
+HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) {
+ HeaderFileInfoVisitor Visitor(*this, FE);
+ ModuleMgr.visit(&HeaderFileInfoVisitor::visit, &Visitor);
+ if (llvm::Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo()) {
+ if (Listener)
+ Listener->ReadHeaderFileInfo(*HFI, FE->getUID());
+ return *HFI;
+ }
+
+ return HeaderFileInfo();
+}
+
+void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
+ // FIXME: Make it work properly with modules.
+ llvm::SmallVector<DiagnosticsEngine::DiagState *, 32> DiagStates;
+ for (ModuleIterator I = ModuleMgr.begin(), E = ModuleMgr.end(); I != E; ++I) {
+ ModuleFile &F = *(*I);
+ unsigned Idx = 0;
+ DiagStates.clear();
+ assert(!Diag.DiagStates.empty());
+ DiagStates.push_back(&Diag.DiagStates.front()); // the command-line one.
+ while (Idx < F.PragmaDiagMappings.size()) {
+ SourceLocation Loc = ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]);
+ unsigned DiagStateID = F.PragmaDiagMappings[Idx++];
+ if (DiagStateID != 0) {
+ Diag.DiagStatePoints.push_back(
+ DiagnosticsEngine::DiagStatePoint(DiagStates[DiagStateID-1],
+ FullSourceLoc(Loc, SourceMgr)));
+ continue;
+ }
+
+ assert(DiagStateID == 0);
+ // A new DiagState was created here.
+ Diag.DiagStates.push_back(*Diag.GetCurDiagState());
+ DiagnosticsEngine::DiagState *NewState = &Diag.DiagStates.back();
+ DiagStates.push_back(NewState);
+ Diag.DiagStatePoints.push_back(
+ DiagnosticsEngine::DiagStatePoint(NewState,
+ FullSourceLoc(Loc, SourceMgr)));
+ while (1) {
+ assert(Idx < F.PragmaDiagMappings.size() &&
+ "Invalid data, didn't find '-1' marking end of diag/map pairs");
+ if (Idx >= F.PragmaDiagMappings.size()) {
+ break; // Something is messed up but at least avoid infinite loop in
+ // release build.
+ }
+ unsigned DiagID = F.PragmaDiagMappings[Idx++];
+ if (DiagID == (unsigned)-1) {
+ break; // no more diag/map pairs for this location.
+ }
+ diag::Mapping Map = (diag::Mapping)F.PragmaDiagMappings[Idx++];
+ DiagnosticMappingInfo MappingInfo = Diag.makeMappingInfo(Map, Loc);
+ Diag.GetCurDiagState()->setMappingInfo(DiagID, MappingInfo);
+ }
+ }
+ }
+}
+
+/// \brief Get the correct cursor and offset for loading a type.
+ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) {
+ GlobalTypeMapType::iterator I = GlobalTypeMap.find(Index);
+ assert(I != GlobalTypeMap.end() && "Corrupted global type map");
+ ModuleFile *M = I->second;
+ return RecordLocation(M, M->TypeOffsets[Index - M->BaseTypeIndex]);
+}
+
+/// \brief Read and return the type with the given index..
+///
+/// The index is the type ID, shifted and minus the number of predefs. This
+/// routine actually reads the record corresponding to the type at the given
+/// location. It is a helper routine for GetType, which deals with reading type
+/// IDs.
+QualType ASTReader::readTypeRecord(unsigned Index) {
+ RecordLocation Loc = TypeCursorForIndex(Index);
+ llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor;
+
+ // Keep track of where we are in the stream, then jump back there
+ // after reading this type.
+ SavedStreamPosition SavedPosition(DeclsCursor);
+
+ ReadingKindTracker ReadingKind(Read_Type, *this);
+
+ // Note that we are loading a type record.
+ Deserializing AType(this);
+
+ unsigned Idx = 0;
+ DeclsCursor.JumpToBit(Loc.Offset);
+ RecordData Record;
+ unsigned Code = DeclsCursor.ReadCode();
+ switch ((TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
+ case TYPE_EXT_QUAL: {
+ if (Record.size() != 2) {
+ Error("Incorrect encoding of extended qualifier type");
+ return QualType();
+ }
+ QualType Base = readType(*Loc.F, Record, Idx);
+ Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[Idx++]);
+ return Context.getQualifiedType(Base, Quals);
+ }
+
+ case TYPE_COMPLEX: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of complex type");
+ return QualType();
+ }
+ QualType ElemType = readType(*Loc.F, Record, Idx);
+ return Context.getComplexType(ElemType);
+ }
+
+ case TYPE_POINTER: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of pointer type");
+ return QualType();
+ }
+ QualType PointeeType = readType(*Loc.F, Record, Idx);
+ return Context.getPointerType(PointeeType);
+ }
+
+ case TYPE_BLOCK_POINTER: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of block pointer type");
+ return QualType();
+ }
+ QualType PointeeType = readType(*Loc.F, Record, Idx);
+ return Context.getBlockPointerType(PointeeType);
+ }
+
+ case TYPE_LVALUE_REFERENCE: {
+ if (Record.size() != 2) {
+ Error("Incorrect encoding of lvalue reference type");
+ return QualType();
+ }
+ QualType PointeeType = readType(*Loc.F, Record, Idx);
+ return Context.getLValueReferenceType(PointeeType, Record[1]);
+ }
+
+ case TYPE_RVALUE_REFERENCE: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of rvalue reference type");
+ return QualType();
+ }
+ QualType PointeeType = readType(*Loc.F, Record, Idx);
+ return Context.getRValueReferenceType(PointeeType);
+ }
+
+ case TYPE_MEMBER_POINTER: {
+ if (Record.size() != 2) {
+ Error("Incorrect encoding of member pointer type");
+ return QualType();
+ }
+ QualType PointeeType = readType(*Loc.F, Record, Idx);
+ QualType ClassType = readType(*Loc.F, Record, Idx);
+ if (PointeeType.isNull() || ClassType.isNull())
+ return QualType();
+
+ return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
+ }
+
+ case TYPE_CONSTANT_ARRAY: {
+ QualType ElementType = readType(*Loc.F, Record, Idx);
+ ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+ unsigned IndexTypeQuals = Record[2];
+ unsigned Idx = 3;
+ llvm::APInt Size = ReadAPInt(Record, Idx);
+ return Context.getConstantArrayType(ElementType, Size,
+ ASM, IndexTypeQuals);
+ }
+
+ case TYPE_INCOMPLETE_ARRAY: {
+ QualType ElementType = readType(*Loc.F, Record, Idx);
+ ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+ unsigned IndexTypeQuals = Record[2];
+ return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
+ }
+
+ case TYPE_VARIABLE_ARRAY: {
+ QualType ElementType = readType(*Loc.F, Record, Idx);
+ ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+ unsigned IndexTypeQuals = Record[2];
+ SourceLocation LBLoc = ReadSourceLocation(*Loc.F, Record[3]);
+ SourceLocation RBLoc = ReadSourceLocation(*Loc.F, Record[4]);
+ return Context.getVariableArrayType(ElementType, ReadExpr(*Loc.F),
+ ASM, IndexTypeQuals,
+ SourceRange(LBLoc, RBLoc));
+ }
+
+ case TYPE_VECTOR: {
+ if (Record.size() != 3) {
+ Error("incorrect encoding of vector type in AST file");
+ return QualType();
+ }
+
+ QualType ElementType = readType(*Loc.F, Record, Idx);
+ unsigned NumElements = Record[1];
+ unsigned VecKind = Record[2];
+ return Context.getVectorType(ElementType, NumElements,
+ (VectorType::VectorKind)VecKind);
+ }
+
+ case TYPE_EXT_VECTOR: {
+ if (Record.size() != 3) {
+ Error("incorrect encoding of extended vector type in AST file");
+ return QualType();
+ }
+
+ QualType ElementType = readType(*Loc.F, Record, Idx);
+ unsigned NumElements = Record[1];
+ return Context.getExtVectorType(ElementType, NumElements);
+ }
+
+ case TYPE_FUNCTION_NO_PROTO: {
+ if (Record.size() != 6) {
+ Error("incorrect encoding of no-proto function type");
+ return QualType();
+ }
+ QualType ResultType = readType(*Loc.F, Record, Idx);
+ FunctionType::ExtInfo Info(Record[1], Record[2], Record[3],
+ (CallingConv)Record[4], Record[5]);
+ return Context.getFunctionNoProtoType(ResultType, Info);
+ }
+
+ case TYPE_FUNCTION_PROTO: {
+ QualType ResultType = readType(*Loc.F, Record, Idx);
+
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.ExtInfo = FunctionType::ExtInfo(/*noreturn*/ Record[1],
+ /*hasregparm*/ Record[2],
+ /*regparm*/ Record[3],
+ static_cast<CallingConv>(Record[4]),
+ /*produces*/ Record[5]);
+
+ unsigned Idx = 6;
+ unsigned NumParams = Record[Idx++];
+ SmallVector<QualType, 16> ParamTypes;
+ for (unsigned I = 0; I != NumParams; ++I)
+ ParamTypes.push_back(readType(*Loc.F, Record, Idx));
+
+ EPI.Variadic = Record[Idx++];
+ EPI.HasTrailingReturn = Record[Idx++];
+ EPI.TypeQuals = Record[Idx++];
+ EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]);
+ ExceptionSpecificationType EST =
+ static_cast<ExceptionSpecificationType>(Record[Idx++]);
+ EPI.ExceptionSpecType = EST;
+ SmallVector<QualType, 2> Exceptions;
+ if (EST == EST_Dynamic) {
+ EPI.NumExceptions = Record[Idx++];
+ for (unsigned I = 0; I != EPI.NumExceptions; ++I)
+ Exceptions.push_back(readType(*Loc.F, Record, Idx));
+ EPI.Exceptions = Exceptions.data();
+ } else if (EST == EST_ComputedNoexcept) {
+ EPI.NoexceptExpr = ReadExpr(*Loc.F);
+ } else if (EST == EST_Uninstantiated) {
+ EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
+ EPI.ExceptionSpecTemplate = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
+ } else if (EST == EST_Unevaluated) {
+ EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record, Idx);
+ }
+ return Context.getFunctionType(ResultType, ParamTypes.data(), NumParams,
+ EPI);
+ }
+
+ case TYPE_UNRESOLVED_USING: {
+ unsigned Idx = 0;
+ return Context.getTypeDeclType(
+ ReadDeclAs<UnresolvedUsingTypenameDecl>(*Loc.F, Record, Idx));
+ }
+
+ case TYPE_TYPEDEF: {
+ if (Record.size() != 2) {
+ Error("incorrect encoding of typedef type");
+ return QualType();
+ }
+ unsigned Idx = 0;
+ TypedefNameDecl *Decl = ReadDeclAs<TypedefNameDecl>(*Loc.F, Record, Idx);
+ QualType Canonical = readType(*Loc.F, Record, Idx);
+ if (!Canonical.isNull())
+ Canonical = Context.getCanonicalType(Canonical);
+ return Context.getTypedefType(Decl, Canonical);
+ }
+
+ case TYPE_TYPEOF_EXPR:
+ return Context.getTypeOfExprType(ReadExpr(*Loc.F));
+
+ case TYPE_TYPEOF: {
+ if (Record.size() != 1) {
+ Error("incorrect encoding of typeof(type) in AST file");
+ return QualType();
+ }
+ QualType UnderlyingType = readType(*Loc.F, Record, Idx);
+ return Context.getTypeOfType(UnderlyingType);
+ }
+
+ case TYPE_DECLTYPE: {
+ QualType UnderlyingType = readType(*Loc.F, Record, Idx);
+ return Context.getDecltypeType(ReadExpr(*Loc.F), UnderlyingType);
+ }
+
+ case TYPE_UNARY_TRANSFORM: {
+ QualType BaseType = readType(*Loc.F, Record, Idx);
+ QualType UnderlyingType = readType(*Loc.F, Record, Idx);
+ UnaryTransformType::UTTKind UKind = (UnaryTransformType::UTTKind)Record[2];
+ return Context.getUnaryTransformType(BaseType, UnderlyingType, UKind);
+ }
+
+ case TYPE_AUTO:
+ return Context.getAutoType(readType(*Loc.F, Record, Idx));
+
+ case TYPE_RECORD: {
+ if (Record.size() != 2) {
+ Error("incorrect encoding of record type");
+ return QualType();
+ }
+ unsigned Idx = 0;
+ bool IsDependent = Record[Idx++];
+ RecordDecl *RD = ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx);
+ RD = cast_or_null<RecordDecl>(RD->getCanonicalDecl());
+ QualType T = Context.getRecordType(RD);
+ const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
+ return T;
+ }
+
+ case TYPE_ENUM: {
+ if (Record.size() != 2) {
+ Error("incorrect encoding of enum type");
+ return QualType();
+ }
+ unsigned Idx = 0;
+ bool IsDependent = Record[Idx++];
+ QualType T
+ = Context.getEnumType(ReadDeclAs<EnumDecl>(*Loc.F, Record, Idx));
+ const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
+ return T;
+ }
+
+ case TYPE_ATTRIBUTED: {
+ if (Record.size() != 3) {
+ Error("incorrect encoding of attributed type");
+ return QualType();
+ }
+ QualType modifiedType = readType(*Loc.F, Record, Idx);
+ QualType equivalentType = readType(*Loc.F, Record, Idx);
+ AttributedType::Kind kind = static_cast<AttributedType::Kind>(Record[2]);
+ return Context.getAttributedType(kind, modifiedType, equivalentType);
+ }
+
+ case TYPE_PAREN: {
+ if (Record.size() != 1) {
+ Error("incorrect encoding of paren type");
+ return QualType();
+ }
+ QualType InnerType = readType(*Loc.F, Record, Idx);
+ return Context.getParenType(InnerType);
+ }
+
+ case TYPE_PACK_EXPANSION: {
+ if (Record.size() != 2) {
+ Error("incorrect encoding of pack expansion type");
+ return QualType();
+ }
+ QualType Pattern = readType(*Loc.F, Record, Idx);
+ if (Pattern.isNull())
+ return QualType();
+ llvm::Optional<unsigned> NumExpansions;
+ if (Record[1])
+ NumExpansions = Record[1] - 1;
+ return Context.getPackExpansionType(Pattern, NumExpansions);
+ }
+
+ case TYPE_ELABORATED: {
+ unsigned Idx = 0;
+ ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
+ NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);
+ QualType NamedType = readType(*Loc.F, Record, Idx);
+ return Context.getElaboratedType(Keyword, NNS, NamedType);
+ }
+
+ case TYPE_OBJC_INTERFACE: {
+ unsigned Idx = 0;
+ ObjCInterfaceDecl *ItfD
+ = ReadDeclAs<ObjCInterfaceDecl>(*Loc.F, Record, Idx);
+ return Context.getObjCInterfaceType(ItfD->getCanonicalDecl());
+ }
+
+ case TYPE_OBJC_OBJECT: {
+ unsigned Idx = 0;
+ QualType Base = readType(*Loc.F, Record, Idx);
+ unsigned NumProtos = Record[Idx++];
+ SmallVector<ObjCProtocolDecl*, 4> Protos;
+ for (unsigned I = 0; I != NumProtos; ++I)
+ Protos.push_back(ReadDeclAs<ObjCProtocolDecl>(*Loc.F, Record, Idx));
+ return Context.getObjCObjectType(Base, Protos.data(), NumProtos);
+ }
+
+ case TYPE_OBJC_OBJECT_POINTER: {
+ unsigned Idx = 0;
+ QualType Pointee = readType(*Loc.F, Record, Idx);
+ return Context.getObjCObjectPointerType(Pointee);
+ }
+
+ case TYPE_SUBST_TEMPLATE_TYPE_PARM: {
+ unsigned Idx = 0;
+ QualType Parm = readType(*Loc.F, Record, Idx);
+ QualType Replacement = readType(*Loc.F, Record, Idx);
+ return
+ Context.getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
+ Replacement);
+ }
+
+ case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: {
+ unsigned Idx = 0;
+ QualType Parm = readType(*Loc.F, Record, Idx);
+ TemplateArgument ArgPack = ReadTemplateArgument(*Loc.F, Record, Idx);
+ return Context.getSubstTemplateTypeParmPackType(
+ cast<TemplateTypeParmType>(Parm),
+ ArgPack);
+ }
+
+ case TYPE_INJECTED_CLASS_NAME: {
+ CXXRecordDecl *D = ReadDeclAs<CXXRecordDecl>(*Loc.F, Record, Idx);
+ QualType TST = readType(*Loc.F, Record, Idx); // probably derivable
+ // FIXME: ASTContext::getInjectedClassNameType is not currently suitable
+ // for AST reading, too much interdependencies.
+ return
+ QualType(new (Context, TypeAlignment) InjectedClassNameType(D, TST), 0);
+ }
+
+ case TYPE_TEMPLATE_TYPE_PARM: {
+ unsigned Idx = 0;
+ unsigned Depth = Record[Idx++];
+ unsigned Index = Record[Idx++];
+ bool Pack = Record[Idx++];
+ TemplateTypeParmDecl *D
+ = ReadDeclAs<TemplateTypeParmDecl>(*Loc.F, Record, Idx);
+ return Context.getTemplateTypeParmType(Depth, Index, Pack, D);
+ }
+
+ case TYPE_DEPENDENT_NAME: {
+ unsigned Idx = 0;
+ ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
+ NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);
+ const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx);
+ QualType Canon = readType(*Loc.F, Record, Idx);
+ if (!Canon.isNull())
+ Canon = Context.getCanonicalType(Canon);
+ return Context.getDependentNameType(Keyword, NNS, Name, Canon);
+ }
+
+ case TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: {
+ unsigned Idx = 0;
+ ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
+ NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);
+ const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx);
+ unsigned NumArgs = Record[Idx++];
+ SmallVector<TemplateArgument, 8> Args;
+ Args.reserve(NumArgs);
+ while (NumArgs--)
+ Args.push_back(ReadTemplateArgument(*Loc.F, Record, Idx));
+ return Context.getDependentTemplateSpecializationType(Keyword, NNS, Name,
+ Args.size(), Args.data());
+ }
+
+ case TYPE_DEPENDENT_SIZED_ARRAY: {
+ unsigned Idx = 0;
+
+ // ArrayType
+ QualType ElementType = readType(*Loc.F, Record, Idx);
+ ArrayType::ArraySizeModifier ASM
+ = (ArrayType::ArraySizeModifier)Record[Idx++];
+ unsigned IndexTypeQuals = Record[Idx++];
+
+ // DependentSizedArrayType
+ Expr *NumElts = ReadExpr(*Loc.F);
+ SourceRange Brackets = ReadSourceRange(*Loc.F, Record, Idx);
+
+ return Context.getDependentSizedArrayType(ElementType, NumElts, ASM,
+ IndexTypeQuals, Brackets);
+ }
+
+ case TYPE_TEMPLATE_SPECIALIZATION: {
+ unsigned Idx = 0;
+ bool IsDependent = Record[Idx++];
+ TemplateName Name = ReadTemplateName(*Loc.F, Record, Idx);
+ SmallVector<TemplateArgument, 8> Args;
+ ReadTemplateArgumentList(Args, *Loc.F, Record, Idx);
+ QualType Underlying = readType(*Loc.F, Record, Idx);
+ QualType T;
+ if (Underlying.isNull())
+ T = Context.getCanonicalTemplateSpecializationType(Name, Args.data(),
+ Args.size());
+ else
+ T = Context.getTemplateSpecializationType(Name, Args.data(),
+ Args.size(), Underlying);
+ const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
+ return T;
+ }
+
+ case TYPE_ATOMIC: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of atomic type");
+ return QualType();
+ }
+ QualType ValueType = readType(*Loc.F, Record, Idx);
+ return Context.getAtomicType(ValueType);
+ }
+ }
+ llvm_unreachable("Invalid TypeCode!");
+}
+
+class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> {
+ ASTReader &Reader;
+ ModuleFile &F;
+ const ASTReader::RecordData &Record;
+ unsigned &Idx;
+
+ SourceLocation ReadSourceLocation(const ASTReader::RecordData &R,
+ unsigned &I) {
+ return Reader.ReadSourceLocation(F, R, I);
+ }
+
+ template<typename T>
+ T *ReadDeclAs(const ASTReader::RecordData &Record, unsigned &Idx) {
+ return Reader.ReadDeclAs<T>(F, Record, Idx);
+ }
+
+public:
+ TypeLocReader(ASTReader &Reader, ModuleFile &F,
+ const ASTReader::RecordData &Record, unsigned &Idx)
+ : Reader(Reader), F(F), Record(Record), Idx(Idx)
+ { }
+
+ // We want compile-time assurance that we've enumerated all of
+ // these, so unfortunately we have to declare them first, then
+ // define them out-of-line.
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
+#include "clang/AST/TypeLocNodes.def"
+
+ void VisitFunctionTypeLoc(FunctionTypeLoc);
+ void VisitArrayTypeLoc(ArrayTypeLoc);
+};
+
+void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ // nothing to do
+}
+void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+ TL.setBuiltinLoc(ReadSourceLocation(Record, Idx));
+ if (TL.needsExtraLocalData()) {
+ TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++]));
+ TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++]));
+ TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++]));
+ TL.setModeAttr(Record[Idx++]);
+ }
+}
+void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
+ TL.setStarLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+ TL.setCaretLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+ TL.setAmpLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+ TL.setAmpAmpLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+ TL.setStarLoc(ReadSourceLocation(Record, Idx));
+ TL.setClassTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
+}
+void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
+ TL.setLBracketLoc(ReadSourceLocation(Record, Idx));
+ TL.setRBracketLoc(ReadSourceLocation(Record, Idx));
+ if (Record[Idx++])
+ TL.setSizeExpr(Reader.ReadExpr(F));
+ else
+ TL.setSizeExpr(0);
+}
+void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitDependentSizedArrayTypeLoc(
+ DependentSizedArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
+ DependentSizedExtVectorTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+ TL.setLocalRangeBegin(ReadSourceLocation(Record, Idx));
+ TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx));
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
+ TL.setArg(i, ReadDeclAs<ParmVarDecl>(Record, Idx));
+ }
+}
+void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
+ VisitFunctionTypeLoc(TL);
+}
+void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
+ VisitFunctionTypeLoc(TL);
+}
+void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+ TL.setTypeofLoc(ReadSourceLocation(Record, Idx));
+ TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+ TL.setTypeofLoc(ReadSourceLocation(Record, Idx));
+ TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
+}
+void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
+ TL.setKWLoc(ReadSourceLocation(Record, Idx));
+ TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
+}
+void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+ TL.setAttrNameLoc(ReadSourceLocation(Record, Idx));
+ if (TL.hasAttrOperand()) {
+ SourceRange range;
+ range.setBegin(ReadSourceLocation(Record, Idx));
+ range.setEnd(ReadSourceLocation(Record, Idx));
+ TL.setAttrOperandParensRange(range);
+ }
+ if (TL.hasAttrExprOperand()) {
+ if (Record[Idx++])
+ TL.setAttrExprOperand(Reader.ReadExpr(F));
+ else
+ TL.setAttrExprOperand(0);
+ } else if (TL.hasAttrEnumOperand())
+ TL.setAttrEnumOperandLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
+ SubstTemplateTypeParmTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc(
+ SubstTemplateTypeParmPackTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTemplateSpecializationTypeLoc(
+ TemplateSpecializationTypeLoc TL) {
+ TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx));
+ TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ TL.setArgLocInfo(i,
+ Reader.GetTemplateArgumentLocInfo(F,
+ TL.getTypePtr()->getArg(i).getKind(),
+ Record, Idx));
+}
+void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) {
+ TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+ TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));
+ TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
+}
+void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+ TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));
+ TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc(
+ DependentTemplateSpecializationTypeLoc TL) {
+ TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));
+ TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
+ TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx));
+ TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
+ TL.setArgLocInfo(I,
+ Reader.GetTemplateArgumentLocInfo(F,
+ TL.getTypePtr()->getArg(I).getKind(),
+ Record, Idx));
+}
+void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
+ TL.setEllipsisLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
+ TL.setHasBaseTypeAsWritten(Record[Idx++]);
+ TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+ for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+ TL.setProtocolLoc(i, ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ TL.setStarLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
+ TL.setKWLoc(ReadSourceLocation(Record, Idx));
+ TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F,
+ const RecordData &Record,
+ unsigned &Idx) {
+ QualType InfoTy = readType(F, Record, Idx);
+ if (InfoTy.isNull())
+ return 0;
+
+ TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy);
+ TypeLocReader TLR(*this, F, Record, Idx);
+ for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
+ TLR.Visit(TL);
+ return TInfo;
+}
+
+QualType ASTReader::GetType(TypeID ID) {
+ unsigned FastQuals = ID & Qualifiers::FastMask;
+ unsigned Index = ID >> Qualifiers::FastWidth;
+
+ if (Index < NUM_PREDEF_TYPE_IDS) {
+ QualType T;
+ switch ((PredefinedTypeIDs)Index) {
+ case PREDEF_TYPE_NULL_ID: return QualType();
+ case PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;
+ case PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;
+
+ case PREDEF_TYPE_CHAR_U_ID:
+ case PREDEF_TYPE_CHAR_S_ID:
+ // FIXME: Check that the signedness of CharTy is correct!
+ T = Context.CharTy;
+ break;
+
+ case PREDEF_TYPE_UCHAR_ID: T = Context.UnsignedCharTy; break;
+ case PREDEF_TYPE_USHORT_ID: T = Context.UnsignedShortTy; break;
+ case PREDEF_TYPE_UINT_ID: T = Context.UnsignedIntTy; break;
+ case PREDEF_TYPE_ULONG_ID: T = Context.UnsignedLongTy; break;
+ case PREDEF_TYPE_ULONGLONG_ID: T = Context.UnsignedLongLongTy; break;
+ case PREDEF_TYPE_UINT128_ID: T = Context.UnsignedInt128Ty; break;
+ case PREDEF_TYPE_SCHAR_ID: T = Context.SignedCharTy; break;
+ case PREDEF_TYPE_WCHAR_ID: T = Context.WCharTy; break;
+ case PREDEF_TYPE_SHORT_ID: T = Context.ShortTy; break;
+ case PREDEF_TYPE_INT_ID: T = Context.IntTy; break;
+ case PREDEF_TYPE_LONG_ID: T = Context.LongTy; break;
+ case PREDEF_TYPE_LONGLONG_ID: T = Context.LongLongTy; break;
+ case PREDEF_TYPE_INT128_ID: T = Context.Int128Ty; break;
+ case PREDEF_TYPE_HALF_ID: T = Context.HalfTy; break;
+ case PREDEF_TYPE_FLOAT_ID: T = Context.FloatTy; break;
+ case PREDEF_TYPE_DOUBLE_ID: T = Context.DoubleTy; break;
+ case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;
+ case PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break;
+ case PREDEF_TYPE_BOUND_MEMBER: T = Context.BoundMemberTy; break;
+ case PREDEF_TYPE_PSEUDO_OBJECT: T = Context.PseudoObjectTy; break;
+ case PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break;
+ case PREDEF_TYPE_UNKNOWN_ANY: T = Context.UnknownAnyTy; break;
+ case PREDEF_TYPE_NULLPTR_ID: T = Context.NullPtrTy; break;
+ case PREDEF_TYPE_CHAR16_ID: T = Context.Char16Ty; break;
+ case PREDEF_TYPE_CHAR32_ID: T = Context.Char32Ty; break;
+ case PREDEF_TYPE_OBJC_ID: T = Context.ObjCBuiltinIdTy; break;
+ case PREDEF_TYPE_OBJC_CLASS: T = Context.ObjCBuiltinClassTy; break;
+ case PREDEF_TYPE_OBJC_SEL: T = Context.ObjCBuiltinSelTy; break;
+ case PREDEF_TYPE_AUTO_DEDUCT: T = Context.getAutoDeductType(); break;
+
+ case PREDEF_TYPE_AUTO_RREF_DEDUCT:
+ T = Context.getAutoRRefDeductType();
+ break;
+
+ case PREDEF_TYPE_ARC_UNBRIDGED_CAST:
+ T = Context.ARCUnbridgedCastTy;
+ break;
+
+ case PREDEF_TYPE_VA_LIST_TAG:
+ T = Context.getVaListTagType();
+ break;
+
+ case PREDEF_TYPE_BUILTIN_FN:
+ T = Context.BuiltinFnTy;
+ break;
+ }
+
+ assert(!T.isNull() && "Unknown predefined type");
+ return T.withFastQualifiers(FastQuals);
+ }
+
+ Index -= NUM_PREDEF_TYPE_IDS;
+ assert(Index < TypesLoaded.size() && "Type index out-of-range");
+ if (TypesLoaded[Index].isNull()) {
+ TypesLoaded[Index] = readTypeRecord(Index);
+ if (TypesLoaded[Index].isNull())
+ return QualType();
+
+ TypesLoaded[Index]->setFromAST();
+ if (DeserializationListener)
+ DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID),
+ TypesLoaded[Index]);
+ }
+
+ return TypesLoaded[Index].withFastQualifiers(FastQuals);
+}
+
+QualType ASTReader::getLocalType(ModuleFile &F, unsigned LocalID) {
+ return GetType(getGlobalTypeID(F, LocalID));
+}
+
+serialization::TypeID
+ASTReader::getGlobalTypeID(ModuleFile &F, unsigned LocalID) const {
+ unsigned FastQuals = LocalID & Qualifiers::FastMask;
+ unsigned LocalIndex = LocalID >> Qualifiers::FastWidth;
+
+ if (LocalIndex < NUM_PREDEF_TYPE_IDS)
+ return LocalID;
+
+ ContinuousRangeMap<uint32_t, int, 2>::iterator I
+ = F.TypeRemap.find(LocalIndex - NUM_PREDEF_TYPE_IDS);
+ assert(I != F.TypeRemap.end() && "Invalid index into type index remap");
+
+ unsigned GlobalIndex = LocalIndex + I->second;
+ return (GlobalIndex << Qualifiers::FastWidth) | FastQuals;
+}
+
+TemplateArgumentLocInfo
+ASTReader::GetTemplateArgumentLocInfo(ModuleFile &F,
+ TemplateArgument::ArgKind Kind,
+ const RecordData &Record,
+ unsigned &Index) {
+ switch (Kind) {
+ case TemplateArgument::Expression:
+ return ReadExpr(F);
+ case TemplateArgument::Type:
+ return GetTypeSourceInfo(F, Record, Index);
+ case TemplateArgument::Template: {
+ NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record,
+ Index);
+ SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
+ return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc,
+ SourceLocation());
+ }
+ case TemplateArgument::TemplateExpansion: {
+ NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record,
+ Index);
+ SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
+ SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index);
+ return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc,
+ EllipsisLoc);
+ }
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::NullPtr:
+ case TemplateArgument::Pack:
+ // FIXME: Is this right?
+ return TemplateArgumentLocInfo();
+ }
+ llvm_unreachable("unexpected template argument loc");
+}
+
+TemplateArgumentLoc
+ASTReader::ReadTemplateArgumentLoc(ModuleFile &F,
+ const RecordData &Record, unsigned &Index) {
+ TemplateArgument Arg = ReadTemplateArgument(F, Record, Index);
+
+ if (Arg.getKind() == TemplateArgument::Expression) {
+ if (Record[Index++]) // bool InfoHasSameExpr.
+ return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr()));
+ }
+ return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(F, Arg.getKind(),
+ Record, Index));
+}
+
+Decl *ASTReader::GetExternalDecl(uint32_t ID) {
+ return GetDecl(ID);
+}
+
+uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record,
+ unsigned &Idx){
+ if (Idx >= Record.size())
+ return 0;
+
+ unsigned LocalID = Record[Idx++];
+ return getGlobalBitOffset(M, M.CXXBaseSpecifiersOffsets[LocalID - 1]);
+}
+
+CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
+ RecordLocation Loc = getLocalBitOffset(Offset);
+ llvm::BitstreamCursor &Cursor = Loc.F->DeclsCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(Loc.Offset);
+ ReadingKindTracker ReadingKind(Read_Decl, *this);
+ RecordData Record;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.ReadRecord(Code, Record);
+ if (RecCode != DECL_CXX_BASE_SPECIFIERS) {
+ Error("Malformed AST file: missing C++ base specifiers");
+ return 0;
+ }
+
+ unsigned Idx = 0;
+ unsigned NumBases = Record[Idx++];
+ void *Mem = Context.Allocate(sizeof(CXXBaseSpecifier) * NumBases);
+ CXXBaseSpecifier *Bases = new (Mem) CXXBaseSpecifier [NumBases];
+ for (unsigned I = 0; I != NumBases; ++I)
+ Bases[I] = ReadCXXBaseSpecifier(*Loc.F, Record, Idx);
+ return Bases;
+}
+
+serialization::DeclID
+ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const {
+ if (LocalID < NUM_PREDEF_DECL_IDS)
+ return LocalID;
+
+ ContinuousRangeMap<uint32_t, int, 2>::iterator I
+ = F.DeclRemap.find(LocalID - NUM_PREDEF_DECL_IDS);
+ assert(I != F.DeclRemap.end() && "Invalid index into decl index remap");
+
+ return LocalID + I->second;
+}
+
+bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID,
+ ModuleFile &M) const {
+ GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(ID);
+ assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
+ return &M == I->second;
+}
+
+ModuleFile *ASTReader::getOwningModuleFile(Decl *D) {
+ if (!D->isFromASTFile())
+ return 0;
+ GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(D->getGlobalID());
+ assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
+ return I->second;
+}
+
+SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) {
+ if (ID < NUM_PREDEF_DECL_IDS)
+ return SourceLocation();
+
+ unsigned Index = ID - NUM_PREDEF_DECL_IDS;
+
+ if (Index > DeclsLoaded.size()) {
+ Error("declaration ID out-of-range for AST file");
+ return SourceLocation();
+ }
+
+ if (Decl *D = DeclsLoaded[Index])
+ return D->getLocation();
+
+ unsigned RawLocation = 0;
+ RecordLocation Rec = DeclCursorForID(ID, RawLocation);
+ return ReadSourceLocation(*Rec.F, RawLocation);
+}
+
+Decl *ASTReader::GetDecl(DeclID ID) {
+ if (ID < NUM_PREDEF_DECL_IDS) {
+ switch ((PredefinedDeclIDs)ID) {
+ case PREDEF_DECL_NULL_ID:
+ return 0;
+
+ case PREDEF_DECL_TRANSLATION_UNIT_ID:
+ return Context.getTranslationUnitDecl();
+
+ case PREDEF_DECL_OBJC_ID_ID:
+ return Context.getObjCIdDecl();
+
+ case PREDEF_DECL_OBJC_SEL_ID:
+ return Context.getObjCSelDecl();
+
+ case PREDEF_DECL_OBJC_CLASS_ID:
+ return Context.getObjCClassDecl();
+
+ case PREDEF_DECL_OBJC_PROTOCOL_ID:
+ return Context.getObjCProtocolDecl();
+
+ case PREDEF_DECL_INT_128_ID:
+ return Context.getInt128Decl();
+
+ case PREDEF_DECL_UNSIGNED_INT_128_ID:
+ return Context.getUInt128Decl();
+
+ case PREDEF_DECL_OBJC_INSTANCETYPE_ID:
+ return Context.getObjCInstanceTypeDecl();
+
+ case PREDEF_DECL_BUILTIN_VA_LIST_ID:
+ return Context.getBuiltinVaListDecl();
+ }
+ }
+
+ unsigned Index = ID - NUM_PREDEF_DECL_IDS;
+
+ if (Index >= DeclsLoaded.size()) {
+ assert(0 && "declaration ID out-of-range for AST file");
+ Error("declaration ID out-of-range for AST file");
+ return 0;
+ }
+
+ if (!DeclsLoaded[Index]) {
+ ReadDeclRecord(ID);
+ if (DeserializationListener)
+ DeserializationListener->DeclRead(ID, DeclsLoaded[Index]);
+ }
+
+ return DeclsLoaded[Index];
+}
+
+DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M,
+ DeclID GlobalID) {
+ if (GlobalID < NUM_PREDEF_DECL_IDS)
+ return GlobalID;
+
+ GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID);
+ assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
+ ModuleFile *Owner = I->second;
+
+ llvm::DenseMap<ModuleFile *, serialization::DeclID>::iterator Pos
+ = M.GlobalToLocalDeclIDs.find(Owner);
+ if (Pos == M.GlobalToLocalDeclIDs.end())
+ return 0;
+
+ return GlobalID - Owner->BaseDeclID + Pos->second;
+}
+
+serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F,
+ const RecordData &Record,
+ unsigned &Idx) {
+ if (Idx >= Record.size()) {
+ Error("Corrupted AST file");
+ return 0;
+ }
+
+ return getGlobalDeclID(F, Record[Idx++]);
+}
+
+/// \brief Resolve the offset of a statement into a statement.
+///
+/// This operation will read a new statement from the external
+/// source each time it is called, and is meant to be used via a
+/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
+Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) {
+ // Switch case IDs are per Decl.
+ ClearSwitchCaseIDs();
+
+ // Offset here is a global offset across the entire chain.
+ RecordLocation Loc = getLocalBitOffset(Offset);
+ Loc.F->DeclsCursor.JumpToBit(Loc.Offset);
+ return ReadStmtFromStream(*Loc.F);
+}
+
+namespace {
+ class FindExternalLexicalDeclsVisitor {
+ ASTReader &Reader;
+ const DeclContext *DC;
+ bool (*isKindWeWant)(Decl::Kind);
+
+ SmallVectorImpl<Decl*> &Decls;
+ bool PredefsVisited[NUM_PREDEF_DECL_IDS];
+
+ public:
+ FindExternalLexicalDeclsVisitor(ASTReader &Reader, const DeclContext *DC,
+ bool (*isKindWeWant)(Decl::Kind),
+ SmallVectorImpl<Decl*> &Decls)
+ : Reader(Reader), DC(DC), isKindWeWant(isKindWeWant), Decls(Decls)
+ {
+ for (unsigned I = 0; I != NUM_PREDEF_DECL_IDS; ++I)
+ PredefsVisited[I] = false;
+ }
+
+ static bool visit(ModuleFile &M, bool Preorder, void *UserData) {
+ if (Preorder)
+ return false;
+
+ FindExternalLexicalDeclsVisitor *This
+ = static_cast<FindExternalLexicalDeclsVisitor *>(UserData);
+
+ ModuleFile::DeclContextInfosMap::iterator Info
+ = M.DeclContextInfos.find(This->DC);
+ if (Info == M.DeclContextInfos.end() || !Info->second.LexicalDecls)
+ return false;
+
+ // Load all of the declaration IDs
+ for (const KindDeclIDPair *ID = Info->second.LexicalDecls,
+ *IDE = ID + Info->second.NumLexicalDecls;
+ ID != IDE; ++ID) {
+ if (This->isKindWeWant && !This->isKindWeWant((Decl::Kind)ID->first))
+ continue;
+
+ // Don't add predefined declarations to the lexical context more
+ // than once.
+ if (ID->second < NUM_PREDEF_DECL_IDS) {
+ if (This->PredefsVisited[ID->second])
+ continue;
+
+ This->PredefsVisited[ID->second] = true;
+ }
+
+ if (Decl *D = This->Reader.GetLocalDecl(M, ID->second)) {
+ if (!This->DC->isDeclInLexicalTraversal(D))
+ This->Decls.push_back(D);
+ }
+ }
+
+ return false;
+ }
+ };
+}
+
+ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC,
+ bool (*isKindWeWant)(Decl::Kind),
+ SmallVectorImpl<Decl*> &Decls) {
+ // There might be lexical decls in multiple modules, for the TU at
+ // least. Walk all of the modules in the order they were loaded.
+ FindExternalLexicalDeclsVisitor Visitor(*this, DC, isKindWeWant, Decls);
+ ModuleMgr.visitDepthFirst(&FindExternalLexicalDeclsVisitor::visit, &Visitor);
+ ++NumLexicalDeclContextsRead;
+ return ELR_Success;
+}
+
+namespace {
+
+class DeclIDComp {
+ ASTReader &Reader;
+ ModuleFile &Mod;
+
+public:
+ DeclIDComp(ASTReader &Reader, ModuleFile &M) : Reader(Reader), Mod(M) {}
+
+ bool operator()(LocalDeclID L, LocalDeclID R) const {
+ SourceLocation LHS = getLocation(L);
+ SourceLocation RHS = getLocation(R);
+ return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+ }
+
+ bool operator()(SourceLocation LHS, LocalDeclID R) const {
+ SourceLocation RHS = getLocation(R);
+ return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+ }
+
+ bool operator()(LocalDeclID L, SourceLocation RHS) const {
+ SourceLocation LHS = getLocation(L);
+ return Reader.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+ }
+
+ SourceLocation getLocation(LocalDeclID ID) const {
+ return Reader.getSourceManager().getFileLoc(
+ Reader.getSourceLocationForDeclID(Reader.getGlobalDeclID(Mod, ID)));
+ }
+};
+
+}
+
+void ASTReader::FindFileRegionDecls(FileID File,
+ unsigned Offset, unsigned Length,
+ SmallVectorImpl<Decl *> &Decls) {
+ SourceManager &SM = getSourceManager();
+
+ llvm::DenseMap<FileID, FileDeclsInfo>::iterator I = FileDeclIDs.find(File);
+ if (I == FileDeclIDs.end())
+ return;
+
+ FileDeclsInfo &DInfo = I->second;
+ if (DInfo.Decls.empty())
+ return;
+
+ SourceLocation
+ BeginLoc = SM.getLocForStartOfFile(File).getLocWithOffset(Offset);
+ SourceLocation EndLoc = BeginLoc.getLocWithOffset(Length);
+
+ DeclIDComp DIDComp(*this, *DInfo.Mod);
+ ArrayRef<serialization::LocalDeclID>::iterator
+ BeginIt = std::lower_bound(DInfo.Decls.begin(), DInfo.Decls.end(),
+ BeginLoc, DIDComp);
+ if (BeginIt != DInfo.Decls.begin())
+ --BeginIt;
+
+ // If we are pointing at a top-level decl inside an objc container, we need
+ // to backtrack until we find it otherwise we will fail to report that the
+ // region overlaps with an objc container.
+ while (BeginIt != DInfo.Decls.begin() &&
+ GetDecl(getGlobalDeclID(*DInfo.Mod, *BeginIt))
+ ->isTopLevelDeclInObjCContainer())
+ --BeginIt;
+
+ ArrayRef<serialization::LocalDeclID>::iterator
+ EndIt = std::upper_bound(DInfo.Decls.begin(), DInfo.Decls.end(),
+ EndLoc, DIDComp);
+ if (EndIt != DInfo.Decls.end())
+ ++EndIt;
+
+ for (ArrayRef<serialization::LocalDeclID>::iterator
+ DIt = BeginIt; DIt != EndIt; ++DIt)
+ Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt)));
+}
+
+namespace {
+ /// \brief ModuleFile visitor used to perform name lookup into a
+ /// declaration context.
+ class DeclContextNameLookupVisitor {
+ ASTReader &Reader;
+ llvm::SmallVectorImpl<const DeclContext *> &Contexts;
+ DeclarationName Name;
+ SmallVectorImpl<NamedDecl *> &Decls;
+
+ public:
+ DeclContextNameLookupVisitor(ASTReader &Reader,
+ SmallVectorImpl<const DeclContext *> &Contexts,
+ DeclarationName Name,
+ SmallVectorImpl<NamedDecl *> &Decls)
+ : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { }
+
+ static bool visit(ModuleFile &M, void *UserData) {
+ DeclContextNameLookupVisitor *This
+ = static_cast<DeclContextNameLookupVisitor *>(UserData);
+
+ // Check whether we have any visible declaration information for
+ // this context in this module.
+ ModuleFile::DeclContextInfosMap::iterator Info;
+ bool FoundInfo = false;
+ for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {
+ Info = M.DeclContextInfos.find(This->Contexts[I]);
+ if (Info != M.DeclContextInfos.end() &&
+ Info->second.NameLookupTableData) {
+ FoundInfo = true;
+ break;
+ }
+ }
+
+ if (!FoundInfo)
+ return false;
+
+ // Look for this name within this module.
+ ASTDeclContextNameLookupTable *LookupTable =
+ Info->second.NameLookupTableData;
+ ASTDeclContextNameLookupTable::iterator Pos
+ = LookupTable->find(This->Name);
+ if (Pos == LookupTable->end())
+ return false;
+
+ bool FoundAnything = false;
+ ASTDeclContextNameLookupTrait::data_type Data = *Pos;
+ for (; Data.first != Data.second; ++Data.first) {
+ NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M, *Data.first);
+ if (!ND)
+ continue;
+
+ if (ND->getDeclName() != This->Name) {
+ // A name might be null because the decl's redeclarable part is
+ // currently read before reading its name. The lookup is triggered by
+ // building that decl (likely indirectly), and so it is later in the
+ // sense of "already existing" and can be ignored here.
+ continue;
+ }
+
+ // Record this declaration.
+ FoundAnything = true;
+ This->Decls.push_back(ND);
+ }
+
+ return FoundAnything;
+ }
+ };
+}
+
+DeclContext::lookup_result
+ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
+ DeclarationName Name) {
+ assert(DC->hasExternalVisibleStorage() &&
+ "DeclContext has no visible decls in storage");
+ if (!Name)
+ return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
+ DeclContext::lookup_iterator(0));
+
+ SmallVector<NamedDecl *, 64> Decls;
+
+ // Compute the declaration contexts we need to look into. Multiple such
+ // declaration contexts occur when two declaration contexts from disjoint
+ // modules get merged, e.g., when two namespaces with the same name are
+ // independently defined in separate modules.
+ SmallVector<const DeclContext *, 2> Contexts;
+ Contexts.push_back(DC);
+
+ if (DC->isNamespace()) {
+ MergedDeclsMap::iterator Merged
+ = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+ if (Merged != MergedDecls.end()) {
+ for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
+ Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
+ }
+ }
+
+ DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
+ ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);
+ ++NumVisibleDeclContextsRead;
+ SetExternalVisibleDeclsForName(DC, Name, Decls);
+ return const_cast<DeclContext*>(DC)->lookup(Name);
+}
+
+namespace {
+ /// \brief ModuleFile visitor used to retrieve all visible names in a
+ /// declaration context.
+ class DeclContextAllNamesVisitor {
+ ASTReader &Reader;
+ llvm::SmallVectorImpl<const DeclContext *> &Contexts;
+ llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> > &Decls;
+
+ public:
+ DeclContextAllNamesVisitor(ASTReader &Reader,
+ SmallVectorImpl<const DeclContext *> &Contexts,
+ llvm::DenseMap<DeclarationName,
+ SmallVector<NamedDecl *, 8> > &Decls)
+ : Reader(Reader), Contexts(Contexts), Decls(Decls) { }
+
+ static bool visit(ModuleFile &M, void *UserData) {
+ DeclContextAllNamesVisitor *This
+ = static_cast<DeclContextAllNamesVisitor *>(UserData);
+
+ // Check whether we have any visible declaration information for
+ // this context in this module.
+ ModuleFile::DeclContextInfosMap::iterator Info;
+ bool FoundInfo = false;
+ for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {
+ Info = M.DeclContextInfos.find(This->Contexts[I]);
+ if (Info != M.DeclContextInfos.end() &&
+ Info->second.NameLookupTableData) {
+ FoundInfo = true;
+ break;
+ }
+ }
+
+ if (!FoundInfo)
+ return false;
+
+ ASTDeclContextNameLookupTable *LookupTable =
+ Info->second.NameLookupTableData;
+ bool FoundAnything = false;
+ for (ASTDeclContextNameLookupTable::data_iterator
+ I = LookupTable->data_begin(), E = LookupTable->data_end();
+ I != E; ++I) {
+ ASTDeclContextNameLookupTrait::data_type Data = *I;
+ for (; Data.first != Data.second; ++Data.first) {
+ NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M,
+ *Data.first);
+ if (!ND)
+ continue;
+
+ // Record this declaration.
+ FoundAnything = true;
+ This->Decls[ND->getDeclName()].push_back(ND);
+ }
+ }
+
+ return FoundAnything;
+ }
+ };
+}
+
+void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {
+ if (!DC->hasExternalVisibleStorage())
+ return;
+ llvm::DenseMap<DeclarationName, llvm::SmallVector<NamedDecl*, 8> > Decls;
+
+ // Compute the declaration contexts we need to look into. Multiple such
+ // declaration contexts occur when two declaration contexts from disjoint
+ // modules get merged, e.g., when two namespaces with the same name are
+ // independently defined in separate modules.
+ SmallVector<const DeclContext *, 2> Contexts;
+ Contexts.push_back(DC);
+
+ if (DC->isNamespace()) {
+ MergedDeclsMap::iterator Merged
+ = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+ if (Merged != MergedDecls.end()) {
+ for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
+ Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
+ }
+ }
+
+ DeclContextAllNamesVisitor Visitor(*this, Contexts, Decls);
+ ModuleMgr.visit(&DeclContextAllNamesVisitor::visit, &Visitor);
+ ++NumVisibleDeclContextsRead;
+
+ for (llvm::DenseMap<DeclarationName,
+ llvm::SmallVector<NamedDecl*, 8> >::iterator
+ I = Decls.begin(), E = Decls.end(); I != E; ++I) {
+ SetExternalVisibleDeclsForName(DC, I->first, I->second);
+ }
+ const_cast<DeclContext *>(DC)->setHasExternalVisibleStorage(false);
+}
+
+/// \brief Under non-PCH compilation the consumer receives the objc methods
+/// before receiving the implementation, and codegen depends on this.
+/// We simulate this by deserializing and passing to consumer the methods of the
+/// implementation before passing the deserialized implementation decl.
+static void PassObjCImplDeclToConsumer(ObjCImplDecl *ImplD,
+ ASTConsumer *Consumer) {
+ assert(ImplD && Consumer);
+
+ for (ObjCImplDecl::method_iterator
+ I = ImplD->meth_begin(), E = ImplD->meth_end(); I != E; ++I)
+ Consumer->HandleInterestingDecl(DeclGroupRef(*I));
+
+ Consumer->HandleInterestingDecl(DeclGroupRef(ImplD));
+}
+
+void ASTReader::PassInterestingDeclsToConsumer() {
+ assert(Consumer);
+ while (!InterestingDecls.empty()) {
+ Decl *D = InterestingDecls.front();
+ InterestingDecls.pop_front();
+
+ PassInterestingDeclToConsumer(D);
+ }
+}
+
+void ASTReader::PassInterestingDeclToConsumer(Decl *D) {
+ if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D))
+ PassObjCImplDeclToConsumer(ImplD, Consumer);
+ else
+ Consumer->HandleInterestingDecl(DeclGroupRef(D));
+}
+
+void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
+ this->Consumer = Consumer;
+
+ if (!Consumer)
+ return;
+
+ for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
+ // Force deserialization of this decl, which will cause it to be queued for
+ // passing to the consumer.
+ GetDecl(ExternalDefinitions[I]);
+ }
+ ExternalDefinitions.clear();
+
+ PassInterestingDeclsToConsumer();
+}
+
+void ASTReader::PrintStats() {
+ std::fprintf(stderr, "*** AST File Statistics:\n");
+
+ unsigned NumTypesLoaded
+ = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
+ QualType());
+ unsigned NumDeclsLoaded
+ = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
+ (Decl *)0);
+ unsigned NumIdentifiersLoaded
+ = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
+ IdentifiersLoaded.end(),
+ (IdentifierInfo *)0);
+ unsigned NumMacrosLoaded
+ = MacrosLoaded.size() - std::count(MacrosLoaded.begin(),
+ MacrosLoaded.end(),
+ (MacroInfo *)0);
+ unsigned NumSelectorsLoaded
+ = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
+ SelectorsLoaded.end(),
+ Selector());
+
+ if (unsigned TotalNumSLocEntries = getTotalNumSLocs())
+ std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",
+ NumSLocEntriesRead, TotalNumSLocEntries,
+ ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
+ if (!TypesLoaded.empty())
+ std::fprintf(stderr, " %u/%u types read (%f%%)\n",
+ NumTypesLoaded, (unsigned)TypesLoaded.size(),
+ ((float)NumTypesLoaded/TypesLoaded.size() * 100));
+ if (!DeclsLoaded.empty())
+ std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
+ NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
+ ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
+ if (!IdentifiersLoaded.empty())
+ std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
+ NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
+ ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
+ if (!MacrosLoaded.empty())
+ std::fprintf(stderr, " %u/%u macros read (%f%%)\n",
+ NumMacrosLoaded, (unsigned)MacrosLoaded.size(),
+ ((float)NumMacrosLoaded/MacrosLoaded.size() * 100));
+ if (!SelectorsLoaded.empty())
+ std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",
+ NumSelectorsLoaded, (unsigned)SelectorsLoaded.size(),
+ ((float)NumSelectorsLoaded/SelectorsLoaded.size() * 100));
+ if (TotalNumStatements)
+ std::fprintf(stderr, " %u/%u statements read (%f%%)\n",
+ NumStatementsRead, TotalNumStatements,
+ ((float)NumStatementsRead/TotalNumStatements * 100));
+ if (TotalNumMacros)
+ std::fprintf(stderr, " %u/%u macros read (%f%%)\n",
+ NumMacrosRead, TotalNumMacros,
+ ((float)NumMacrosRead/TotalNumMacros * 100));
+ if (TotalLexicalDeclContexts)
+ std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n",
+ NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
+ ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
+ * 100));
+ if (TotalVisibleDeclContexts)
+ std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n",
+ NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
+ ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
+ * 100));
+ if (TotalNumMethodPoolEntries) {
+ std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",
+ NumMethodPoolEntriesRead, TotalNumMethodPoolEntries,
+ ((float)NumMethodPoolEntriesRead/TotalNumMethodPoolEntries
+ * 100));
+ std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses);
+ }
+ std::fprintf(stderr, "\n");
+ dump();
+ std::fprintf(stderr, "\n");
+}
+
+template<typename Key, typename ModuleFile, unsigned InitialCapacity>
+static void
+dumpModuleIDMap(StringRef Name,
+ const ContinuousRangeMap<Key, ModuleFile *,
+ InitialCapacity> &Map) {
+ if (Map.begin() == Map.end())
+ return;
+
+ typedef ContinuousRangeMap<Key, ModuleFile *, InitialCapacity> MapType;
+ llvm::errs() << Name << ":\n";
+ for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end();
+ I != IEnd; ++I) {
+ llvm::errs() << " " << I->first << " -> " << I->second->FileName
+ << "\n";
+ }
+}
+
+void ASTReader::dump() {
+ llvm::errs() << "*** PCH/ModuleFile Remappings:\n";
+ dumpModuleIDMap("Global bit offset map", GlobalBitOffsetsMap);
+ dumpModuleIDMap("Global source location entry map", GlobalSLocEntryMap);
+ dumpModuleIDMap("Global type map", GlobalTypeMap);
+ dumpModuleIDMap("Global declaration map", GlobalDeclMap);
+ dumpModuleIDMap("Global identifier map", GlobalIdentifierMap);
+ dumpModuleIDMap("Global macro map", GlobalMacroMap);
+ dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap);
+ dumpModuleIDMap("Global selector map", GlobalSelectorMap);
+ dumpModuleIDMap("Global preprocessed entity map",
+ GlobalPreprocessedEntityMap);
+
+ llvm::errs() << "\n*** PCH/Modules Loaded:";
+ for (ModuleManager::ModuleConstIterator M = ModuleMgr.begin(),
+ MEnd = ModuleMgr.end();
+ M != MEnd; ++M)
+ (*M)->dump();
+}
+
+/// Return the amount of memory used by memory buffers, breaking down
+/// by heap-backed versus mmap'ed memory.
+void ASTReader::getMemoryBufferSizes(MemoryBufferSizes &sizes) const {
+ for (ModuleConstIterator I = ModuleMgr.begin(),
+ E = ModuleMgr.end(); I != E; ++I) {
+ if (llvm::MemoryBuffer *buf = (*I)->Buffer.get()) {
+ size_t bytes = buf->getBufferSize();
+ switch (buf->getBufferKind()) {
+ case llvm::MemoryBuffer::MemoryBuffer_Malloc:
+ sizes.malloc_bytes += bytes;
+ break;
+ case llvm::MemoryBuffer::MemoryBuffer_MMap:
+ sizes.mmap_bytes += bytes;
+ break;
+ }
+ }
+ }
+}
+
+void ASTReader::InitializeSema(Sema &S) {
+ SemaObj = &S;
+ S.addExternalSource(this);
+
+ // Makes sure any declarations that were deserialized "too early"
+ // still get added to the identifier's declaration chains.
+ for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
+ SemaObj->pushExternalDeclIntoScope(PreloadedDecls[I],
+ PreloadedDecls[I]->getDeclName());
+ }
+ PreloadedDecls.clear();
+
+ // Load the offsets of the declarations that Sema references.
+ // They will be lazily deserialized when needed.
+ if (!SemaDeclRefs.empty()) {
+ assert(SemaDeclRefs.size() == 2 && "More decl refs than expected!");
+ if (!SemaObj->StdNamespace)
+ SemaObj->StdNamespace = SemaDeclRefs[0];
+ if (!SemaObj->StdBadAlloc)
+ SemaObj->StdBadAlloc = SemaDeclRefs[1];
+ }
+
+ if (!FPPragmaOptions.empty()) {
+ assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS");
+ SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0];
+ }
+
+ if (!OpenCLExtensions.empty()) {
+ unsigned I = 0;
+#define OPENCLEXT(nm) SemaObj->OpenCLFeatures.nm = OpenCLExtensions[I++];
+#include "clang/Basic/OpenCLExtensions.def"
+
+ assert(OpenCLExtensions.size() == I && "Wrong number of OPENCL_EXTENSIONS");
+ }
+}
+
+IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
+ // Note that we are loading an identifier.
+ Deserializing AnIdentifier(this);
+
+ IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart),
+ /*PriorGeneration=*/0);
+ ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
+ IdentifierInfo *II = Visitor.getIdentifierInfo();
+ markIdentifierUpToDate(II);
+ return II;
+}
+
+namespace clang {
+ /// \brief An identifier-lookup iterator that enumerates all of the
+ /// identifiers stored within a set of AST files.
+ class ASTIdentifierIterator : public IdentifierIterator {
+ /// \brief The AST reader whose identifiers are being enumerated.
+ const ASTReader &Reader;
+
+ /// \brief The current index into the chain of AST files stored in
+ /// the AST reader.
+ unsigned Index;
+
+ /// \brief The current position within the identifier lookup table
+ /// of the current AST file.
+ ASTIdentifierLookupTable::key_iterator Current;
+
+ /// \brief The end position within the identifier lookup table of
+ /// the current AST file.
+ ASTIdentifierLookupTable::key_iterator End;
+
+ public:
+ explicit ASTIdentifierIterator(const ASTReader &Reader);
+
+ virtual StringRef Next();
+ };
+}
+
+ASTIdentifierIterator::ASTIdentifierIterator(const ASTReader &Reader)
+ : Reader(Reader), Index(Reader.ModuleMgr.size() - 1) {
+ ASTIdentifierLookupTable *IdTable
+ = (ASTIdentifierLookupTable *)Reader.ModuleMgr[Index].IdentifierLookupTable;
+ Current = IdTable->key_begin();
+ End = IdTable->key_end();
+}
+
+StringRef ASTIdentifierIterator::Next() {
+ while (Current == End) {
+ // If we have exhausted all of our AST files, we're done.
+ if (Index == 0)
+ return StringRef();
+
+ --Index;
+ ASTIdentifierLookupTable *IdTable
+ = (ASTIdentifierLookupTable *)Reader.ModuleMgr[Index].
+ IdentifierLookupTable;
+ Current = IdTable->key_begin();
+ End = IdTable->key_end();
+ }
+
+ // We have any identifiers remaining in the current AST file; return
+ // the next one.
+ std::pair<const char*, unsigned> Key = *Current;
+ ++Current;
+ return StringRef(Key.first, Key.second);
+}
+
+IdentifierIterator *ASTReader::getIdentifiers() const {
+ return new ASTIdentifierIterator(*this);
+}
+
+namespace clang { namespace serialization {
+ class ReadMethodPoolVisitor {
+ ASTReader &Reader;
+ Selector Sel;
+ unsigned PriorGeneration;
+ llvm::SmallVector<ObjCMethodDecl *, 4> InstanceMethods;
+ llvm::SmallVector<ObjCMethodDecl *, 4> FactoryMethods;
+
+ public:
+ ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel,
+ unsigned PriorGeneration)
+ : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration) { }
+
+ static bool visit(ModuleFile &M, void *UserData) {
+ ReadMethodPoolVisitor *This
+ = static_cast<ReadMethodPoolVisitor *>(UserData);
+
+ if (!M.SelectorLookupTable)
+ return false;
+
+ // If we've already searched this module file, skip it now.
+ if (M.Generation <= This->PriorGeneration)
+ return true;
+
+ ASTSelectorLookupTable *PoolTable
+ = (ASTSelectorLookupTable*)M.SelectorLookupTable;
+ ASTSelectorLookupTable::iterator Pos = PoolTable->find(This->Sel);
+ if (Pos == PoolTable->end())
+ return false;
+
+ ++This->Reader.NumSelectorsRead;
+ // FIXME: Not quite happy with the statistics here. We probably should
+ // disable this tracking when called via LoadSelector.
+ // Also, should entries without methods count as misses?
+ ++This->Reader.NumMethodPoolEntriesRead;
+ ASTSelectorLookupTrait::data_type Data = *Pos;
+ if (This->Reader.DeserializationListener)
+ This->Reader.DeserializationListener->SelectorRead(Data.ID,
+ This->Sel);
+
+ This->InstanceMethods.append(Data.Instance.begin(), Data.Instance.end());
+ This->FactoryMethods.append(Data.Factory.begin(), Data.Factory.end());
+ return true;
+ }
+
+ /// \brief Retrieve the instance methods found by this visitor.
+ ArrayRef<ObjCMethodDecl *> getInstanceMethods() const {
+ return InstanceMethods;
+ }
+
+ /// \brief Retrieve the instance methods found by this visitor.
+ ArrayRef<ObjCMethodDecl *> getFactoryMethods() const {
+ return FactoryMethods;
+ }
+ };
+} } // end namespace clang::serialization
+
+/// \brief Add the given set of methods to the method list.
+static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods,
+ ObjCMethodList &List) {
+ for (unsigned I = 0, N = Methods.size(); I != N; ++I) {
+ S.addMethodToGlobalList(&List, Methods[I]);
+ }
+}
+
+void ASTReader::ReadMethodPool(Selector Sel) {
+ // Get the selector generation and update it to the current generation.
+ unsigned &Generation = SelectorGeneration[Sel];
+ unsigned PriorGeneration = Generation;
+ Generation = CurrentGeneration;
+
+ // Search for methods defined with this selector.
+ ReadMethodPoolVisitor Visitor(*this, Sel, PriorGeneration);
+ ModuleMgr.visit(&ReadMethodPoolVisitor::visit, &Visitor);
+
+ if (Visitor.getInstanceMethods().empty() &&
+ Visitor.getFactoryMethods().empty()) {
+ ++NumMethodPoolMisses;
+ return;
+ }
+
+ if (!getSema())
+ return;
+
+ Sema &S = *getSema();
+ Sema::GlobalMethodPool::iterator Pos
+ = S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethods())).first;
+
+ addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first);
+ addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second);
+}
+
+void ASTReader::ReadKnownNamespaces(
+ SmallVectorImpl<NamespaceDecl *> &Namespaces) {
+ Namespaces.clear();
+
+ for (unsigned I = 0, N = KnownNamespaces.size(); I != N; ++I) {
+ if (NamespaceDecl *Namespace
+ = dyn_cast_or_null<NamespaceDecl>(GetDecl(KnownNamespaces[I])))
+ Namespaces.push_back(Namespace);
+ }
+}
+
+void ASTReader::ReadTentativeDefinitions(
+ SmallVectorImpl<VarDecl *> &TentativeDefs) {
+ for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
+ VarDecl *Var = dyn_cast_or_null<VarDecl>(GetDecl(TentativeDefinitions[I]));
+ if (Var)
+ TentativeDefs.push_back(Var);
+ }
+ TentativeDefinitions.clear();
+}
+
+void ASTReader::ReadUnusedFileScopedDecls(
+ SmallVectorImpl<const DeclaratorDecl *> &Decls) {
+ for (unsigned I = 0, N = UnusedFileScopedDecls.size(); I != N; ++I) {
+ DeclaratorDecl *D
+ = dyn_cast_or_null<DeclaratorDecl>(GetDecl(UnusedFileScopedDecls[I]));
+ if (D)
+ Decls.push_back(D);
+ }
+ UnusedFileScopedDecls.clear();
+}
+
+void ASTReader::ReadDelegatingConstructors(
+ SmallVectorImpl<CXXConstructorDecl *> &Decls) {
+ for (unsigned I = 0, N = DelegatingCtorDecls.size(); I != N; ++I) {
+ CXXConstructorDecl *D
+ = dyn_cast_or_null<CXXConstructorDecl>(GetDecl(DelegatingCtorDecls[I]));
+ if (D)
+ Decls.push_back(D);
+ }
+ DelegatingCtorDecls.clear();
+}
+
+void ASTReader::ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {
+ for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) {
+ TypedefNameDecl *D
+ = dyn_cast_or_null<TypedefNameDecl>(GetDecl(ExtVectorDecls[I]));
+ if (D)
+ Decls.push_back(D);
+ }
+ ExtVectorDecls.clear();
+}
+
+void ASTReader::ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) {
+ for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) {
+ CXXRecordDecl *D
+ = dyn_cast_or_null<CXXRecordDecl>(GetDecl(DynamicClasses[I]));
+ if (D)
+ Decls.push_back(D);
+ }
+ DynamicClasses.clear();
+}
+
+void
+ASTReader::ReadLocallyScopedExternalDecls(SmallVectorImpl<NamedDecl *> &Decls) {
+ for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
+ NamedDecl *D
+ = dyn_cast_or_null<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
+ if (D)
+ Decls.push_back(D);
+ }
+ LocallyScopedExternalDecls.clear();
+}
+
+void ASTReader::ReadReferencedSelectors(
+ SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {
+ if (ReferencedSelectorsData.empty())
+ return;
+
+ // If there are @selector references added them to its pool. This is for
+ // implementation of -Wselector.
+ unsigned int DataSize = ReferencedSelectorsData.size()-1;
+ unsigned I = 0;
+ while (I < DataSize) {
+ Selector Sel = DecodeSelector(ReferencedSelectorsData[I++]);
+ SourceLocation SelLoc
+ = SourceLocation::getFromRawEncoding(ReferencedSelectorsData[I++]);
+ Sels.push_back(std::make_pair(Sel, SelLoc));
+ }
+ ReferencedSelectorsData.clear();
+}
+
+void ASTReader::ReadWeakUndeclaredIdentifiers(
+ SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WeakIDs) {
+ if (WeakUndeclaredIdentifiers.empty())
+ return;
+
+ for (unsigned I = 0, N = WeakUndeclaredIdentifiers.size(); I < N; /*none*/) {
+ IdentifierInfo *WeakId
+ = DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]);
+ IdentifierInfo *AliasId
+ = DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]);
+ SourceLocation Loc
+ = SourceLocation::getFromRawEncoding(WeakUndeclaredIdentifiers[I++]);
+ bool Used = WeakUndeclaredIdentifiers[I++];
+ WeakInfo WI(AliasId, Loc);
+ WI.setUsed(Used);
+ WeakIDs.push_back(std::make_pair(WeakId, WI));
+ }
+ WeakUndeclaredIdentifiers.clear();
+}
+
+void ASTReader::ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {
+ for (unsigned Idx = 0, N = VTableUses.size(); Idx < N; /* In loop */) {
+ ExternalVTableUse VT;
+ VT.Record = dyn_cast_or_null<CXXRecordDecl>(GetDecl(VTableUses[Idx++]));
+ VT.Location = SourceLocation::getFromRawEncoding(VTableUses[Idx++]);
+ VT.DefinitionRequired = VTableUses[Idx++];
+ VTables.push_back(VT);
+ }
+
+ VTableUses.clear();
+}
+
+void ASTReader::ReadPendingInstantiations(
+ SmallVectorImpl<std::pair<ValueDecl *, SourceLocation> > &Pending) {
+ for (unsigned Idx = 0, N = PendingInstantiations.size(); Idx < N;) {
+ ValueDecl *D = cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++]));
+ SourceLocation Loc
+ = SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]);
+
+ Pending.push_back(std::make_pair(D, Loc));
+ }
+ PendingInstantiations.clear();
+}
+
+void ASTReader::LoadSelector(Selector Sel) {
+ // It would be complicated to avoid reading the methods anyway. So don't.
+ ReadMethodPool(Sel);
+}
+
+void ASTReader::SetIdentifierInfo(IdentifierID ID, IdentifierInfo *II) {
+ assert(ID && "Non-zero identifier ID required");
+ assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
+ IdentifiersLoaded[ID - 1] = II;
+ if (DeserializationListener)
+ DeserializationListener->IdentifierRead(ID, II);
+}
+
+/// \brief Set the globally-visible declarations associated with the given
+/// identifier.
+///
+/// If the AST reader is currently in a state where the given declaration IDs
+/// cannot safely be resolved, they are queued until it is safe to resolve
+/// them.
+///
+/// \param II an IdentifierInfo that refers to one or more globally-visible
+/// declarations.
+///
+/// \param DeclIDs the set of declaration IDs with the name @p II that are
+/// visible at global scope.
+///
+/// \param Nonrecursive should be true to indicate that the caller knows that
+/// this call is non-recursive, and therefore the globally-visible declarations
+/// will not be placed onto the pending queue.
+void
+ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II,
+ const SmallVectorImpl<uint32_t> &DeclIDs,
+ bool Nonrecursive) {
+ if (NumCurrentElementsDeserializing && !Nonrecursive) {
+ PendingIdentifierInfos.push_back(PendingIdentifierInfo());
+ PendingIdentifierInfo &PII = PendingIdentifierInfos.back();
+ PII.II = II;
+ PII.DeclIDs.append(DeclIDs.begin(), DeclIDs.end());
+ return;
+ }
+
+ for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
+ NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
+ if (SemaObj) {
+ // Introduce this declaration into the translation-unit scope
+ // and add it to the declaration chain for this identifier, so
+ // that (unqualified) name lookup will find it.
+ SemaObj->pushExternalDeclIntoScope(D, II);
+ } else {
+ // Queue this declaration so that it will be added to the
+ // translation unit scope and identifier's declaration chain
+ // once a Sema object is known.
+ PreloadedDecls.push_back(D);
+ }
+ }
+}
+
+IdentifierInfo *ASTReader::DecodeIdentifierInfo(IdentifierID ID) {
+ if (ID == 0)
+ return 0;
+
+ if (IdentifiersLoaded.empty()) {
+ Error("no identifier table in AST file");
+ return 0;
+ }
+
+ ID -= 1;
+ if (!IdentifiersLoaded[ID]) {
+ GlobalIdentifierMapType::iterator I = GlobalIdentifierMap.find(ID + 1);
+ assert(I != GlobalIdentifierMap.end() && "Corrupted global identifier map");
+ ModuleFile *M = I->second;
+ unsigned Index = ID - M->BaseIdentifierID;
+ const char *Str = M->IdentifierTableData + M->IdentifierOffsets[Index];
+
+ // All of the strings in the AST file are preceded by a 16-bit length.
+ // Extract that 16-bit length to avoid having to execute strlen().
+ // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
+ // unsigned integers. This is important to avoid integer overflow when
+ // we cast them to 'unsigned'.
+ const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
+ unsigned StrLen = (((unsigned) StrLenPtr[0])
+ | (((unsigned) StrLenPtr[1]) << 8)) - 1;
+ IdentifiersLoaded[ID]
+ = &PP.getIdentifierTable().get(StringRef(Str, StrLen));
+ if (DeserializationListener)
+ DeserializationListener->IdentifierRead(ID + 1, IdentifiersLoaded[ID]);
+ }
+
+ return IdentifiersLoaded[ID];
+}
+
+IdentifierInfo *ASTReader::getLocalIdentifier(ModuleFile &M, unsigned LocalID) {
+ return DecodeIdentifierInfo(getGlobalIdentifierID(M, LocalID));
+}
+
+IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) {
+ if (LocalID < NUM_PREDEF_IDENT_IDS)
+ return LocalID;
+
+ ContinuousRangeMap<uint32_t, int, 2>::iterator I
+ = M.IdentifierRemap.find(LocalID - NUM_PREDEF_IDENT_IDS);
+ assert(I != M.IdentifierRemap.end()
+ && "Invalid index into identifier index remap");
+
+ return LocalID + I->second;
+}
+
+MacroInfo *ASTReader::getMacro(MacroID ID, MacroInfo *Hint) {
+ if (ID == 0)
+ return 0;
+
+ if (MacrosLoaded.empty()) {
+ Error("no macro table in AST file");
+ return 0;
+ }
+
+ ID -= NUM_PREDEF_MACRO_IDS;
+ if (!MacrosLoaded[ID]) {
+ GlobalMacroMapType::iterator I
+ = GlobalMacroMap.find(ID + NUM_PREDEF_MACRO_IDS);
+ assert(I != GlobalMacroMap.end() && "Corrupted global macro map");
+ ModuleFile *M = I->second;
+ unsigned Index = ID - M->BaseMacroID;
+ ReadMacroRecord(*M, M->MacroOffsets[Index], Hint);
+ }
+
+ return MacrosLoaded[ID];
+}
+
+MacroID ASTReader::getGlobalMacroID(ModuleFile &M, unsigned LocalID) {
+ if (LocalID < NUM_PREDEF_MACRO_IDS)
+ return LocalID;
+
+ ContinuousRangeMap<uint32_t, int, 2>::iterator I
+ = M.MacroRemap.find(LocalID - NUM_PREDEF_MACRO_IDS);
+ assert(I != M.MacroRemap.end() && "Invalid index into macro index remap");
+
+ return LocalID + I->second;
+}
+
+serialization::SubmoduleID
+ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) {
+ if (LocalID < NUM_PREDEF_SUBMODULE_IDS)
+ return LocalID;
+
+ ContinuousRangeMap<uint32_t, int, 2>::iterator I
+ = M.SubmoduleRemap.find(LocalID - NUM_PREDEF_SUBMODULE_IDS);
+ assert(I != M.SubmoduleRemap.end()
+ && "Invalid index into submodule index remap");
+
+ return LocalID + I->second;
+}
+
+Module *ASTReader::getSubmodule(SubmoduleID GlobalID) {
+ if (GlobalID < NUM_PREDEF_SUBMODULE_IDS) {
+ assert(GlobalID == 0 && "Unhandled global submodule ID");
+ return 0;
+ }
+
+ if (GlobalID > SubmodulesLoaded.size()) {
+ Error("submodule ID out of range in AST file");
+ return 0;
+ }
+
+ return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS];
+}
+
+Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) {
+ return DecodeSelector(getGlobalSelectorID(M, LocalID));
+}
+
+Selector ASTReader::DecodeSelector(serialization::SelectorID ID) {
+ if (ID == 0)
+ return Selector();
+
+ if (ID > SelectorsLoaded.size()) {
+ Error("selector ID out of range in AST file");
+ return Selector();
+ }
+
+ if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) {
+ // Load this selector from the selector table.
+ GlobalSelectorMapType::iterator I = GlobalSelectorMap.find(ID);
+ assert(I != GlobalSelectorMap.end() && "Corrupted global selector map");
+ ModuleFile &M = *I->second;
+ ASTSelectorLookupTrait Trait(*this, M);
+ unsigned Idx = ID - M.BaseSelectorID - NUM_PREDEF_SELECTOR_IDS;
+ SelectorsLoaded[ID - 1] =
+ Trait.ReadKey(M.SelectorLookupTableData + M.SelectorOffsets[Idx], 0);
+ if (DeserializationListener)
+ DeserializationListener->SelectorRead(ID, SelectorsLoaded[ID - 1]);
+ }
+
+ return SelectorsLoaded[ID - 1];
+}
+
+Selector ASTReader::GetExternalSelector(serialization::SelectorID ID) {
+ return DecodeSelector(ID);
+}
+
+uint32_t ASTReader::GetNumExternalSelectors() {
+ // ID 0 (the null selector) is considered an external selector.
+ return getTotalNumSelectors() + 1;
+}
+
+serialization::SelectorID
+ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const {
+ if (LocalID < NUM_PREDEF_SELECTOR_IDS)
+ return LocalID;
+
+ ContinuousRangeMap<uint32_t, int, 2>::iterator I
+ = M.SelectorRemap.find(LocalID - NUM_PREDEF_SELECTOR_IDS);
+ assert(I != M.SelectorRemap.end()
+ && "Invalid index into selector index remap");
+
+ return LocalID + I->second;
+}
+
+DeclarationName
+ASTReader::ReadDeclarationName(ModuleFile &F,
+ const RecordData &Record, unsigned &Idx) {
+ DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
+ switch (Kind) {
+ case DeclarationName::Identifier:
+ return DeclarationName(GetIdentifierInfo(F, Record, Idx));
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ return DeclarationName(ReadSelector(F, Record, Idx));
+
+ case DeclarationName::CXXConstructorName:
+ return Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(readType(F, Record, Idx)));
+
+ case DeclarationName::CXXDestructorName:
+ return Context.DeclarationNames.getCXXDestructorName(
+ Context.getCanonicalType(readType(F, Record, Idx)));
+
+ case DeclarationName::CXXConversionFunctionName:
+ return Context.DeclarationNames.getCXXConversionFunctionName(
+ Context.getCanonicalType(readType(F, Record, Idx)));
+
+ case DeclarationName::CXXOperatorName:
+ return Context.DeclarationNames.getCXXOperatorName(
+ (OverloadedOperatorKind)Record[Idx++]);
+
+ case DeclarationName::CXXLiteralOperatorName:
+ return Context.DeclarationNames.getCXXLiteralOperatorName(
+ GetIdentifierInfo(F, Record, Idx));
+
+ case DeclarationName::CXXUsingDirective:
+ return DeclarationName::getUsingDirectiveName();
+ }
+
+ llvm_unreachable("Invalid NameKind!");
+}
+
+void ASTReader::ReadDeclarationNameLoc(ModuleFile &F,
+ DeclarationNameLoc &DNLoc,
+ DeclarationName Name,
+ const RecordData &Record, unsigned &Idx) {
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ DNLoc.NamedType.TInfo = GetTypeSourceInfo(F, Record, Idx);
+ break;
+
+ case DeclarationName::CXXOperatorName:
+ DNLoc.CXXOperatorName.BeginOpNameLoc
+ = ReadSourceLocation(F, Record, Idx).getRawEncoding();
+ DNLoc.CXXOperatorName.EndOpNameLoc
+ = ReadSourceLocation(F, Record, Idx).getRawEncoding();
+ break;
+
+ case DeclarationName::CXXLiteralOperatorName:
+ DNLoc.CXXLiteralOperatorName.OpNameLoc
+ = ReadSourceLocation(F, Record, Idx).getRawEncoding();
+ break;
+
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+}
+
+void ASTReader::ReadDeclarationNameInfo(ModuleFile &F,
+ DeclarationNameInfo &NameInfo,
+ const RecordData &Record, unsigned &Idx) {
+ NameInfo.setName(ReadDeclarationName(F, Record, Idx));
+ NameInfo.setLoc(ReadSourceLocation(F, Record, Idx));
+ DeclarationNameLoc DNLoc;
+ ReadDeclarationNameLoc(F, DNLoc, NameInfo.getName(), Record, Idx);
+ NameInfo.setInfo(DNLoc);
+}
+
+void ASTReader::ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info,
+ const RecordData &Record, unsigned &Idx) {
+ Info.QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx);
+ unsigned NumTPLists = Record[Idx++];
+ Info.NumTemplParamLists = NumTPLists;
+ if (NumTPLists) {
+ Info.TemplParamLists = new (Context) TemplateParameterList*[NumTPLists];
+ for (unsigned i=0; i != NumTPLists; ++i)
+ Info.TemplParamLists[i] = ReadTemplateParameterList(F, Record, Idx);
+ }
+}
+
+TemplateName
+ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx) {
+ TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++];
+ switch (Kind) {
+ case TemplateName::Template:
+ return TemplateName(ReadDeclAs<TemplateDecl>(F, Record, Idx));
+
+ case TemplateName::OverloadedTemplate: {
+ unsigned size = Record[Idx++];
+ UnresolvedSet<8> Decls;
+ while (size--)
+ Decls.addDecl(ReadDeclAs<NamedDecl>(F, Record, Idx));
+
+ return Context.getOverloadedTemplateName(Decls.begin(), Decls.end());
+ }
+
+ case TemplateName::QualifiedTemplate: {
+ NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx);
+ bool hasTemplKeyword = Record[Idx++];
+ TemplateDecl *Template = ReadDeclAs<TemplateDecl>(F, Record, Idx);
+ return Context.getQualifiedTemplateName(NNS, hasTemplKeyword, Template);
+ }
+
+ case TemplateName::DependentTemplate: {
+ NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx);
+ if (Record[Idx++]) // isIdentifier
+ return Context.getDependentTemplateName(NNS,
+ GetIdentifierInfo(F, Record,
+ Idx));
+ return Context.getDependentTemplateName(NNS,
+ (OverloadedOperatorKind)Record[Idx++]);
+ }
+
+ case TemplateName::SubstTemplateTemplateParm: {
+ TemplateTemplateParmDecl *param
+ = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx);
+ if (!param) return TemplateName();
+ TemplateName replacement = ReadTemplateName(F, Record, Idx);
+ return Context.getSubstTemplateTemplateParm(param, replacement);
+ }
+
+ case TemplateName::SubstTemplateTemplateParmPack: {
+ TemplateTemplateParmDecl *Param
+ = ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx);
+ if (!Param)
+ return TemplateName();
+
+ TemplateArgument ArgPack = ReadTemplateArgument(F, Record, Idx);
+ if (ArgPack.getKind() != TemplateArgument::Pack)
+ return TemplateName();
+
+ return Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
+ }
+ }
+
+ llvm_unreachable("Unhandled template name kind!");
+}
+
+TemplateArgument
+ASTReader::ReadTemplateArgument(ModuleFile &F,
+ const RecordData &Record, unsigned &Idx) {
+ TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];
+ switch (Kind) {
+ case TemplateArgument::Null:
+ return TemplateArgument();
+ case TemplateArgument::Type:
+ return TemplateArgument(readType(F, Record, Idx));
+ case TemplateArgument::Declaration: {
+ ValueDecl *D = ReadDeclAs<ValueDecl>(F, Record, Idx);
+ bool ForReferenceParam = Record[Idx++];
+ return TemplateArgument(D, ForReferenceParam);
+ }
+ case TemplateArgument::NullPtr:
+ return TemplateArgument(readType(F, Record, Idx), /*isNullPtr*/true);
+ case TemplateArgument::Integral: {
+ llvm::APSInt Value = ReadAPSInt(Record, Idx);
+ QualType T = readType(F, Record, Idx);
+ return TemplateArgument(Context, Value, T);
+ }
+ case TemplateArgument::Template:
+ return TemplateArgument(ReadTemplateName(F, Record, Idx));
+ case TemplateArgument::TemplateExpansion: {
+ TemplateName Name = ReadTemplateName(F, Record, Idx);
+ llvm::Optional<unsigned> NumTemplateExpansions;
+ if (unsigned NumExpansions = Record[Idx++])
+ NumTemplateExpansions = NumExpansions - 1;
+ return TemplateArgument(Name, NumTemplateExpansions);
+ }
+ case TemplateArgument::Expression:
+ return TemplateArgument(ReadExpr(F));
+ case TemplateArgument::Pack: {
+ unsigned NumArgs = Record[Idx++];
+ TemplateArgument *Args = new (Context) TemplateArgument[NumArgs];
+ for (unsigned I = 0; I != NumArgs; ++I)
+ Args[I] = ReadTemplateArgument(F, Record, Idx);
+ return TemplateArgument(Args, NumArgs);
+ }
+ }
+
+ llvm_unreachable("Unhandled template argument kind!");
+}
+
+TemplateParameterList *
+ASTReader::ReadTemplateParameterList(ModuleFile &F,
+ const RecordData &Record, unsigned &Idx) {
+ SourceLocation TemplateLoc = ReadSourceLocation(F, Record, Idx);
+ SourceLocation LAngleLoc = ReadSourceLocation(F, Record, Idx);
+ SourceLocation RAngleLoc = ReadSourceLocation(F, Record, Idx);
+
+ unsigned NumParams = Record[Idx++];
+ SmallVector<NamedDecl *, 16> Params;
+ Params.reserve(NumParams);
+ while (NumParams--)
+ Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx));
+
+ TemplateParameterList* TemplateParams =
+ TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,
+ Params.data(), Params.size(), RAngleLoc);
+ return TemplateParams;
+}
+
+void
+ASTReader::
+ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs,
+ ModuleFile &F, const RecordData &Record,
+ unsigned &Idx) {
+ unsigned NumTemplateArgs = Record[Idx++];
+ TemplArgs.reserve(NumTemplateArgs);
+ while (NumTemplateArgs--)
+ TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx));
+}
+
+/// \brief Read a UnresolvedSet structure.
+void ASTReader::ReadUnresolvedSet(ModuleFile &F, ASTUnresolvedSet &Set,
+ const RecordData &Record, unsigned &Idx) {
+ unsigned NumDecls = Record[Idx++];
+ Set.reserve(Context, NumDecls);
+ while (NumDecls--) {
+ NamedDecl *D = ReadDeclAs<NamedDecl>(F, Record, Idx);
+ AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
+ Set.addDecl(Context, D, AS);
+ }
+}
+
+CXXBaseSpecifier
+ASTReader::ReadCXXBaseSpecifier(ModuleFile &F,
+ const RecordData &Record, unsigned &Idx) {
+ bool isVirtual = static_cast<bool>(Record[Idx++]);
+ bool isBaseOfClass = static_cast<bool>(Record[Idx++]);
+ AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]);
+ bool inheritConstructors = static_cast<bool>(Record[Idx++]);
+ TypeSourceInfo *TInfo = GetTypeSourceInfo(F, Record, Idx);
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Idx);
+ CXXBaseSpecifier Result(Range, isVirtual, isBaseOfClass, AS, TInfo,
+ EllipsisLoc);
+ Result.setInheritConstructors(inheritConstructors);
+ return Result;
+}
+
+std::pair<CXXCtorInitializer **, unsigned>
+ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx) {
+ CXXCtorInitializer **CtorInitializers = 0;
+ unsigned NumInitializers = Record[Idx++];
+ if (NumInitializers) {
+ CtorInitializers
+ = new (Context) CXXCtorInitializer*[NumInitializers];
+ for (unsigned i=0; i != NumInitializers; ++i) {
+ TypeSourceInfo *TInfo = 0;
+ bool IsBaseVirtual = false;
+ FieldDecl *Member = 0;
+ IndirectFieldDecl *IndirectMember = 0;
+
+ CtorInitializerType Type = (CtorInitializerType)Record[Idx++];
+ switch (Type) {
+ case CTOR_INITIALIZER_BASE:
+ TInfo = GetTypeSourceInfo(F, Record, Idx);
+ IsBaseVirtual = Record[Idx++];
+ break;
+
+ case CTOR_INITIALIZER_DELEGATING:
+ TInfo = GetTypeSourceInfo(F, Record, Idx);
+ break;
+
+ case CTOR_INITIALIZER_MEMBER:
+ Member = ReadDeclAs<FieldDecl>(F, Record, Idx);
+ break;
+
+ case CTOR_INITIALIZER_INDIRECT_MEMBER:
+ IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx);
+ break;
+ }
+
+ SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx);
+ Expr *Init = ReadExpr(F);
+ SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);
+ SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);
+ bool IsWritten = Record[Idx++];
+ unsigned SourceOrderOrNumArrayIndices;
+ SmallVector<VarDecl *, 8> Indices;
+ if (IsWritten) {
+ SourceOrderOrNumArrayIndices = Record[Idx++];
+ } else {
+ SourceOrderOrNumArrayIndices = Record[Idx++];
+ Indices.reserve(SourceOrderOrNumArrayIndices);
+ for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
+ Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx));
+ }
+
+ CXXCtorInitializer *BOMInit;
+ if (Type == CTOR_INITIALIZER_BASE) {
+ BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual,
+ LParenLoc, Init, RParenLoc,
+ MemberOrEllipsisLoc);
+ } else if (Type == CTOR_INITIALIZER_DELEGATING) {
+ BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc,
+ Init, RParenLoc);
+ } else if (IsWritten) {
+ if (Member)
+ BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc);
+ else
+ BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember,
+ MemberOrEllipsisLoc, LParenLoc,
+ Init, RParenLoc);
+ } else {
+ BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc,
+ Indices.data(), Indices.size());
+ }
+
+ if (IsWritten)
+ BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);
+ CtorInitializers[i] = BOMInit;
+ }
+ }
+
+ return std::make_pair(CtorInitializers, NumInitializers);
+}
+
+NestedNameSpecifier *
+ASTReader::ReadNestedNameSpecifier(ModuleFile &F,
+ const RecordData &Record, unsigned &Idx) {
+ unsigned N = Record[Idx++];
+ NestedNameSpecifier *NNS = 0, *Prev = 0;
+ for (unsigned I = 0; I != N; ++I) {
+ NestedNameSpecifier::SpecifierKind Kind
+ = (NestedNameSpecifier::SpecifierKind)Record[Idx++];
+ switch (Kind) {
+ case NestedNameSpecifier::Identifier: {
+ IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx);
+ NNS = NestedNameSpecifier::Create(Context, Prev, II);
+ break;
+ }
+
+ case NestedNameSpecifier::Namespace: {
+ NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx);
+ NNS = NestedNameSpecifier::Create(Context, Prev, NS);
+ break;
+ }
+
+ case NestedNameSpecifier::NamespaceAlias: {
+ NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx);
+ NNS = NestedNameSpecifier::Create(Context, Prev, Alias);
+ break;
+ }
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ const Type *T = readType(F, Record, Idx).getTypePtrOrNull();
+ if (!T)
+ return 0;
+
+ bool Template = Record[Idx++];
+ NNS = NestedNameSpecifier::Create(Context, Prev, Template, T);
+ break;
+ }
+
+ case NestedNameSpecifier::Global: {
+ NNS = NestedNameSpecifier::GlobalSpecifier(Context);
+ // No associated value, and there can't be a prefix.
+ break;
+ }
+ }
+ Prev = NNS;
+ }
+ return NNS;
+}
+
+NestedNameSpecifierLoc
+ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx) {
+ unsigned N = Record[Idx++];
+ NestedNameSpecifierLocBuilder Builder;
+ for (unsigned I = 0; I != N; ++I) {
+ NestedNameSpecifier::SpecifierKind Kind
+ = (NestedNameSpecifier::SpecifierKind)Record[Idx++];
+ switch (Kind) {
+ case NestedNameSpecifier::Identifier: {
+ IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx);
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ Builder.Extend(Context, II, Range.getBegin(), Range.getEnd());
+ break;
+ }
+
+ case NestedNameSpecifier::Namespace: {
+ NamespaceDecl *NS = ReadDeclAs<NamespaceDecl>(F, Record, Idx);
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ Builder.Extend(Context, NS, Range.getBegin(), Range.getEnd());
+ break;
+ }
+
+ case NestedNameSpecifier::NamespaceAlias: {
+ NamespaceAliasDecl *Alias =ReadDeclAs<NamespaceAliasDecl>(F, Record, Idx);
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ Builder.Extend(Context, Alias, Range.getBegin(), Range.getEnd());
+ break;
+ }
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ bool Template = Record[Idx++];
+ TypeSourceInfo *T = GetTypeSourceInfo(F, Record, Idx);
+ if (!T)
+ return NestedNameSpecifierLoc();
+ SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
+
+ // FIXME: 'template' keyword location not saved anywhere, so we fake it.
+ Builder.Extend(Context,
+ Template? T->getTypeLoc().getBeginLoc() : SourceLocation(),
+ T->getTypeLoc(), ColonColonLoc);
+ break;
+ }
+
+ case NestedNameSpecifier::Global: {
+ SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
+ Builder.MakeGlobal(Context, ColonColonLoc);
+ break;
+ }
+ }
+ }
+
+ return Builder.getWithLocInContext(Context);
+}
+
+SourceRange
+ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx) {
+ SourceLocation beg = ReadSourceLocation(F, Record, Idx);
+ SourceLocation end = ReadSourceLocation(F, Record, Idx);
+ return SourceRange(beg, end);
+}
+
+/// \brief Read an integral value
+llvm::APInt ASTReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
+ unsigned BitWidth = Record[Idx++];
+ unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
+ llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
+ Idx += NumWords;
+ return Result;
+}
+
+/// \brief Read a signed integral value
+llvm::APSInt ASTReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
+ bool isUnsigned = Record[Idx++];
+ return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
+}
+
+/// \brief Read a floating-point value
+llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
+ return llvm::APFloat(ReadAPInt(Record, Idx));
+}
+
+// \brief Read a string
+std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) {
+ unsigned Len = Record[Idx++];
+ std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
+ Idx += Len;
+ return Result;
+}
+
+VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record,
+ unsigned &Idx) {
+ unsigned Major = Record[Idx++];
+ unsigned Minor = Record[Idx++];
+ unsigned Subminor = Record[Idx++];
+ if (Minor == 0)
+ return VersionTuple(Major);
+ if (Subminor == 0)
+ return VersionTuple(Major, Minor - 1);
+ return VersionTuple(Major, Minor - 1, Subminor - 1);
+}
+
+CXXTemporary *ASTReader::ReadCXXTemporary(ModuleFile &F,
+ const RecordData &Record,
+ unsigned &Idx) {
+ CXXDestructorDecl *Decl = ReadDeclAs<CXXDestructorDecl>(F, Record, Idx);
+ return CXXTemporary::Create(Context, Decl);
+}
+
+DiagnosticBuilder ASTReader::Diag(unsigned DiagID) {
+ return Diag(SourceLocation(), DiagID);
+}
+
+DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) {
+ return Diags.Report(Loc, DiagID);
+}
+
+/// \brief Retrieve the identifier table associated with the
+/// preprocessor.
+IdentifierTable &ASTReader::getIdentifierTable() {
+ return PP.getIdentifierTable();
+}
+
+/// \brief Record that the given ID maps to the given switch-case
+/// statement.
+void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
+ assert((*CurrSwitchCaseStmts)[ID] == 0 &&
+ "Already have a SwitchCase with this ID");
+ (*CurrSwitchCaseStmts)[ID] = SC;
+}
+
+/// \brief Retrieve the switch-case statement with the given ID.
+SwitchCase *ASTReader::getSwitchCaseWithID(unsigned ID) {
+ assert((*CurrSwitchCaseStmts)[ID] != 0 && "No SwitchCase with this ID");
+ return (*CurrSwitchCaseStmts)[ID];
+}
+
+void ASTReader::ClearSwitchCaseIDs() {
+ CurrSwitchCaseStmts->clear();
+}
+
+void ASTReader::ReadComments() {
+ std::vector<RawComment *> Comments;
+ for (SmallVectorImpl<std::pair<llvm::BitstreamCursor,
+ serialization::ModuleFile *> >::iterator
+ I = CommentsCursors.begin(),
+ E = CommentsCursors.end();
+ I != E; ++I) {
+ llvm::BitstreamCursor &Cursor = I->first;
+ serialization::ModuleFile &F = *I->second;
+ SavedStreamPosition SavedPosition(Cursor);
+
+ RecordData Record;
+ while (true) {
+ unsigned Code = Cursor.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK)
+ break;
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ Cursor.ReadSubBlockID();
+ if (Cursor.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Cursor.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read a record.
+ Record.clear();
+ switch ((CommentRecordTypes) Cursor.ReadRecord(Code, Record)) {
+ case COMMENTS_RAW_COMMENT: {
+ unsigned Idx = 0;
+ SourceRange SR = ReadSourceRange(F, Record, Idx);
+ RawComment::CommentKind Kind =
+ (RawComment::CommentKind) Record[Idx++];
+ bool IsTrailingComment = Record[Idx++];
+ bool IsAlmostTrailingComment = Record[Idx++];
+ Comments.push_back(new (Context) RawComment(SR, Kind,
+ IsTrailingComment,
+ IsAlmostTrailingComment));
+ break;
+ }
+ }
+ }
+ }
+ Context.Comments.addCommentsToFront(Comments);
+}
+
+void ASTReader::finishPendingActions() {
+ while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() ||
+ !PendingMacroIDs.empty()) {
+ // If any identifiers with corresponding top-level declarations have
+ // been loaded, load those declarations now.
+ while (!PendingIdentifierInfos.empty()) {
+ SetGloballyVisibleDecls(PendingIdentifierInfos.front().II,
+ PendingIdentifierInfos.front().DeclIDs, true);
+ PendingIdentifierInfos.pop_front();
+ }
+
+ // Load pending declaration chains.
+ for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
+ loadPendingDeclChain(PendingDeclChains[I]);
+ PendingDeclChainsKnown.erase(PendingDeclChains[I]);
+ }
+ PendingDeclChains.clear();
+
+ // Load any pending macro definitions.
+ for (unsigned I = 0; I != PendingMacroIDs.size(); ++I) {
+ // FIXME: std::move here
+ SmallVector<MacroID, 2> GlobalIDs = PendingMacroIDs.begin()[I].second;
+ MacroInfo *Hint = 0;
+ for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
+ ++IDIdx) {
+ Hint = getMacro(GlobalIDs[IDIdx], Hint);
+ }
+ }
+ PendingMacroIDs.clear();
+ }
+
+ // If we deserialized any C++ or Objective-C class definitions, any
+ // Objective-C protocol definitions, or any redeclarable templates, make sure
+ // that all redeclarations point to the definitions. Note that this can only
+ // happen now, after the redeclaration chains have been fully wired.
+ for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
+ DEnd = PendingDefinitions.end();
+ D != DEnd; ++D) {
+ if (TagDecl *TD = dyn_cast<TagDecl>(*D)) {
+ if (const TagType *TagT = dyn_cast<TagType>(TD->TypeForDecl)) {
+ // Make sure that the TagType points at the definition.
+ const_cast<TagType*>(TagT)->decl = TD;
+ }
+
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) {
+ for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(),
+ REnd = RD->redecls_end();
+ R != REnd; ++R)
+ cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData;
+
+ }
+
+ continue;
+ }
+
+ if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) {
+ // Make sure that the ObjCInterfaceType points at the definition.
+ const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl))
+ ->Decl = ID;
+
+ for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(),
+ REnd = ID->redecls_end();
+ R != REnd; ++R)
+ R->Data = ID->Data;
+
+ continue;
+ }
+
+ if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) {
+ for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(),
+ REnd = PD->redecls_end();
+ R != REnd; ++R)
+ R->Data = PD->Data;
+
+ continue;
+ }
+
+ RedeclarableTemplateDecl *RTD
+ = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl();
+ for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(),
+ REnd = RTD->redecls_end();
+ R != REnd; ++R)
+ R->Common = RTD->Common;
+ }
+ PendingDefinitions.clear();
+
+ // Load the bodies of any functions or methods we've encountered. We do
+ // this now (delayed) so that we can be sure that the declaration chains
+ // have been fully wired up.
+ for (PendingBodiesMap::iterator PB = PendingBodies.begin(),
+ PBEnd = PendingBodies.end();
+ PB != PBEnd; ++PB) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PB->first)) {
+ // FIXME: Check for =delete/=default?
+ // FIXME: Complain about ODR violations here?
+ if (!getContext().getLangOpts().Modules || !FD->hasBody())
+ FD->setLazyBody(PB->second);
+ continue;
+ }
+
+ ObjCMethodDecl *MD = cast<ObjCMethodDecl>(PB->first);
+ if (!getContext().getLangOpts().Modules || !MD->hasBody())
+ MD->setLazyBody(PB->second);
+ }
+ PendingBodies.clear();
+}
+
+void ASTReader::FinishedDeserializing() {
+ assert(NumCurrentElementsDeserializing &&
+ "FinishedDeserializing not paired with StartedDeserializing");
+ if (NumCurrentElementsDeserializing == 1) {
+ // We decrease NumCurrentElementsDeserializing only after pending actions
+ // are finished, to avoid recursively re-calling finishPendingActions().
+ finishPendingActions();
+ }
+ --NumCurrentElementsDeserializing;
+
+ if (NumCurrentElementsDeserializing == 0 &&
+ Consumer && !PassingDeclsToConsumer) {
+ // Guard variable to avoid recursively redoing the process of passing
+ // decls to consumer.
+ SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer,
+ true);
+
+ while (!InterestingDecls.empty()) {
+ // We are not in recursive loading, so it's safe to pass the "interesting"
+ // decls to the consumer.
+ Decl *D = InterestingDecls.front();
+ InterestingDecls.pop_front();
+ PassInterestingDeclToConsumer(D);
+ }
+ }
+}
+
+ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
+ StringRef isysroot, bool DisableValidation,
+ bool AllowASTWithCompilerErrors)
+ : Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
+ SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
+ Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context),
+ Consumer(0), ModuleMgr(PP.getFileManager()),
+ isysroot(isysroot), DisableValidation(DisableValidation),
+ AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
+ CurrentGeneration(0), CurrSwitchCaseStmts(&SwitchCaseStmts),
+ NumSLocEntriesRead(0), TotalNumSLocEntries(0),
+ NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0),
+ TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0),
+ NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0),
+ NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0),
+ NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
+ TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0),
+ PassingDeclsToConsumer(false),
+ NumCXXBaseSpecifiersLoaded(0)
+{
+ SourceMgr.setExternalSLocEntrySource(this);
+}
+
+ASTReader::~ASTReader() {
+ for (DeclContextVisibleUpdatesPending::iterator
+ I = PendingVisibleUpdates.begin(),
+ E = PendingVisibleUpdates.end();
+ I != E; ++I) {
+ for (DeclContextVisibleUpdates::iterator J = I->second.begin(),
+ F = I->second.end();
+ J != F; ++J)
+ delete J->first;
+ }
+}
+++ /dev/null
-// RUN: %clang_cc1 %s -emit-llvm -o - -O0 | FileCheck %s\r
-\r
-void fnc1(image1d_t img) {}\r
-// CHECK: @fnc1(%opencl.image1d_t*\r
-\r
-void fnc1arr(image1d_array_t img) {}\r
-// CHECK: @fnc1arr(%opencl.image1d_array_t*\r
-\r
-void fnc1buff(image1d_buffer_t img) {}\r
-// CHECK: @fnc1buff(%opencl.image1d_buffer_t*\r
-\r
-void fnc2(image2d_t img) {}\r
-// CHECK: @fnc2(%opencl.image2d_t*\r
-\r
-void fnc2arr(image2d_array_t img) {}\r
-// CHECK: @fnc2arr(%opencl.image2d_array_t*\r
-\r
-void fnc3(image3d_t img) {}\r
-// CHECK: @fnc3(%opencl.image3d_t*\r
-\r
-kernel void foo(image1d_t img) {\r
-}\r
+++ /dev/null
-// Test this without pch.\r
-// RUN: %clang_cc1 -include %S/ocl_types.h -fsyntax-only %s\r
-\r
-// Test with pch.\r
-// RUN: %clang_cc1 -x cl -emit-pch -o %t %S/ocl_types.h\r
-// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -ast-print\r
-\r
-void foo1(img1d_t img);\r
-\r
-void foo2(img1darr_t img);\r
-\r
-void foo3(img1dbuff_t img);\r
-\r
-void foo4(img2d_t img);\r
-\r
-void foo5(img2darr_t img);\r
-\r
-void foo6(img3d_t img);\r
+++ /dev/null
-/* Used with the ocl_types.cl test */\r
-\r
-// image1d_t\r
-typedef image1d_t img1d_t;\r
-\r
-// image1d_array_t\r
-typedef image1d_array_t img1darr_t;\r
-\r
-// image1d_buffer_t\r
-typedef image1d_buffer_t img1dbuff_t;\r
-\r
-// image2d_t\r
-typedef image2d_t img2d_t;\r
-\r
-// image2d_array_t\r
-typedef image2d_array_t img2darr_t;\r
-\r
-// image3d_t\r
-typedef image3d_t img3d_t;\r
-// RUN: %clang_cc1 %s -fsyntax-only\r
-\r
-__kernel void f__ro(__read_only image2d_t a) { }\r
-\r
-__kernel void f__wo(__write_only image2d_t a) { }\r
-\r
-__kernel void f__rw(__read_write image2d_t a) { }\r
-\r
-\r
-__kernel void fro(read_only image2d_t a) { }\r
-\r
-__kernel void fwo(write_only image2d_t a) { }\r
-\r
-__kernel void frw(read_write image2d_t a) { }\r
+// RUN: %clang_cc1 %s -fsyntax-only
+
+typedef void* image2d_t;
+
+__kernel void f__ro(__read_only image2d_t a) { }
+
+__kernel void f__wo(__write_only image2d_t a) { }
+
+__kernel void f__rw(__read_write image2d_t a) { }
+
+
+__kernel void fro(read_only image2d_t a) { }
+
+__kernel void fwo(write_only image2d_t a) { }
+
+__kernel void frw(read_write image2d_t a) { }
-//===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This file implements the main API hooks in the Clang-C Source Indexing\r
-// library.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "CIndexer.h"\r
-#include "CIndexDiagnostic.h"\r
-#include "CXComment.h"\r
-#include "CXCursor.h"\r
-#include "CXSourceLocation.h"\r
-#include "CXString.h"\r
-#include "CXTranslationUnit.h"\r
-#include "CXType.h"\r
-#include "CursorVisitor.h"\r
-#include "clang/AST/StmtVisitor.h"\r
-#include "clang/Basic/Diagnostic.h"\r
-#include "clang/Basic/Version.h"\r
-#include "clang/Frontend/ASTUnit.h"\r
-#include "clang/Frontend/CompilerInstance.h"\r
-#include "clang/Frontend/FrontendDiagnostic.h"\r
-#include "clang/Lex/HeaderSearch.h"\r
-#include "clang/Lex/Lexer.h"\r
-#include "clang/Lex/PreprocessingRecord.h"\r
-#include "clang/Lex/Preprocessor.h"\r
-#include "llvm/ADT/Optional.h"\r
-#include "llvm/ADT/STLExtras.h"\r
-#include "llvm/ADT/StringSwitch.h"\r
-#include "llvm/Support/Compiler.h"\r
-#include "llvm/Support/CrashRecoveryContext.h"\r
-#include "llvm/Support/MemoryBuffer.h"\r
-#include "llvm/Support/Mutex.h"\r
-#include "llvm/Support/PrettyStackTrace.h"\r
-#include "llvm/Support/Program.h"\r
-#include "llvm/Support/SaveAndRestore.h"\r
-#include "llvm/Support/Signals.h"\r
-#include "llvm/Support/Threading.h"\r
-#include "llvm/Support/Timer.h"\r
-#include "llvm/Support/raw_ostream.h"\r
-\r
-using namespace clang;\r
-using namespace clang::cxcursor;\r
-using namespace clang::cxstring;\r
-using namespace clang::cxtu;\r
-using namespace clang::cxindex;\r
-\r
-CXTranslationUnit cxtu::MakeCXTranslationUnit(CIndexer *CIdx, ASTUnit *TU) {\r
- if (!TU)\r
- return 0;\r
- CXTranslationUnit D = new CXTranslationUnitImpl();\r
- D->CIdx = CIdx;\r
- D->TUData = TU;\r
- D->StringPool = createCXStringPool();\r
- D->Diagnostics = 0;\r
- D->OverridenCursorsPool = createOverridenCXCursorsPool();\r
- return D;\r
-}\r
-\r
-cxtu::CXTUOwner::~CXTUOwner() {\r
- if (TU)\r
- clang_disposeTranslationUnit(TU);\r
-}\r
-\r
-/// \brief Compare two source ranges to determine their relative position in\r
-/// the translation unit.\r
-static RangeComparisonResult RangeCompare(SourceManager &SM,\r
- SourceRange R1,\r
- SourceRange R2) {\r
- assert(R1.isValid() && "First range is invalid?");\r
- assert(R2.isValid() && "Second range is invalid?");\r
- if (R1.getEnd() != R2.getBegin() &&\r
- SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin()))\r
- return RangeBefore;\r
- if (R2.getEnd() != R1.getBegin() &&\r
- SM.isBeforeInTranslationUnit(R2.getEnd(), R1.getBegin()))\r
- return RangeAfter;\r
- return RangeOverlap;\r
-}\r
-\r
-/// \brief Determine if a source location falls within, before, or after a\r
-/// a given source range.\r
-static RangeComparisonResult LocationCompare(SourceManager &SM,\r
- SourceLocation L, SourceRange R) {\r
- assert(R.isValid() && "First range is invalid?");\r
- assert(L.isValid() && "Second range is invalid?");\r
- if (L == R.getBegin() || L == R.getEnd())\r
- return RangeOverlap;\r
- if (SM.isBeforeInTranslationUnit(L, R.getBegin()))\r
- return RangeBefore;\r
- if (SM.isBeforeInTranslationUnit(R.getEnd(), L))\r
- return RangeAfter;\r
- return RangeOverlap;\r
-}\r
-\r
-/// \brief Translate a Clang source range into a CIndex source range.\r
-///\r
-/// Clang internally represents ranges where the end location points to the\r
-/// start of the token at the end. However, for external clients it is more\r
-/// useful to have a CXSourceRange be a proper half-open interval. This routine\r
-/// does the appropriate translation.\r
-CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,\r
- const LangOptions &LangOpts,\r
- const CharSourceRange &R) {\r
- // We want the last character in this location, so we will adjust the\r
- // location accordingly.\r
- SourceLocation EndLoc = R.getEnd();\r
- if (EndLoc.isValid() && EndLoc.isMacroID() && !SM.isMacroArgExpansion(EndLoc))\r
- EndLoc = SM.getExpansionRange(EndLoc).second;\r
- if (R.isTokenRange() && !EndLoc.isInvalid()) {\r
- unsigned Length = Lexer::MeasureTokenLength(SM.getSpellingLoc(EndLoc),\r
- SM, LangOpts);\r
- EndLoc = EndLoc.getLocWithOffset(Length);\r
- }\r
-\r
- CXSourceRange Result = { { (void *)&SM, (void *)&LangOpts },\r
- R.getBegin().getRawEncoding(),\r
- EndLoc.getRawEncoding() };\r
- return Result;\r
-}\r
-\r
-//===----------------------------------------------------------------------===//\r
-// Cursor visitor.\r
-//===----------------------------------------------------------------------===//\r
-\r
-static SourceRange getRawCursorExtent(CXCursor C);\r
-static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr);\r
-\r
-\r
-RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {\r
- return RangeCompare(AU->getSourceManager(), R, RegionOfInterest);\r
-}\r
-\r
-/// \brief Visit the given cursor and, if requested by the visitor,\r
-/// its children.\r
-///\r
-/// \param Cursor the cursor to visit.\r
-///\r
-/// \param CheckedRegionOfInterest if true, then the caller already checked\r
-/// that this cursor is within the region of interest.\r
-///\r
-/// \returns true if the visitation should be aborted, false if it\r
-/// should continue.\r
-bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) {\r
- if (clang_isInvalid(Cursor.kind))\r
- return false;\r
-\r
- if (clang_isDeclaration(Cursor.kind)) {\r
- Decl *D = getCursorDecl(Cursor);\r
- if (!D) {\r
- assert(0 && "Invalid declaration cursor");\r
- return true; // abort.\r
- }\r
- \r
- // Ignore implicit declarations, unless it's an objc method because\r
- // currently we should report implicit methods for properties when indexing.\r
- if (D->isImplicit() && !isa<ObjCMethodDecl>(D))\r
- return false;\r
- }\r
-\r
- // If we have a range of interest, and this cursor doesn't intersect with it,\r
- // we're done.\r
- if (RegionOfInterest.isValid() && !CheckedRegionOfInterest) {\r
- SourceRange Range = getRawCursorExtent(Cursor);\r
- if (Range.isInvalid() || CompareRegionOfInterest(Range))\r
- return false;\r
- }\r
-\r
- switch (Visitor(Cursor, Parent, ClientData)) {\r
- case CXChildVisit_Break:\r
- return true;\r
-\r
- case CXChildVisit_Continue:\r
- return false;\r
-\r
- case CXChildVisit_Recurse: {\r
- bool ret = VisitChildren(Cursor);\r
- if (PostChildrenVisitor)\r
- if (PostChildrenVisitor(Cursor, ClientData))\r
- return true;\r
- return ret;\r
- }\r
- }\r
-\r
- llvm_unreachable("Invalid CXChildVisitResult!");\r
-}\r
-\r
-static bool visitPreprocessedEntitiesInRange(SourceRange R,\r
- PreprocessingRecord &PPRec,\r
- CursorVisitor &Visitor) {\r
- SourceManager &SM = Visitor.getASTUnit()->getSourceManager();\r
- FileID FID;\r
- \r
- if (!Visitor.shouldVisitIncludedEntities()) {\r
- // If the begin/end of the range lie in the same FileID, do the optimization\r
- // where we skip preprocessed entities that do not come from the same FileID.\r
- FID = SM.getFileID(SM.getFileLoc(R.getBegin()));\r
- if (FID != SM.getFileID(SM.getFileLoc(R.getEnd())))\r
- FID = FileID();\r
- }\r
-\r
- std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>\r
- Entities = PPRec.getPreprocessedEntitiesInRange(R);\r
- return Visitor.visitPreprocessedEntities(Entities.first, Entities.second,\r
- PPRec, FID);\r
-}\r
-\r
-void CursorVisitor::visitFileRegion() {\r
- if (RegionOfInterest.isInvalid())\r
- return;\r
-\r
- ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData);\r
- SourceManager &SM = Unit->getSourceManager();\r
- \r
- std::pair<FileID, unsigned>\r
- Begin = SM.getDecomposedLoc(SM.getFileLoc(RegionOfInterest.getBegin())), \r
- End = SM.getDecomposedLoc(SM.getFileLoc(RegionOfInterest.getEnd())); \r
-\r
- if (End.first != Begin.first) {\r
- // If the end does not reside in the same file, try to recover by\r
- // picking the end of the file of begin location.\r
- End.first = Begin.first;\r
- End.second = SM.getFileIDSize(Begin.first);\r
- }\r
-\r
- assert(Begin.first == End.first);\r
- if (Begin.second > End.second)\r
- return;\r
- \r
- FileID File = Begin.first;\r
- unsigned Offset = Begin.second;\r
- unsigned Length = End.second - Begin.second;\r
-\r
- if (!VisitDeclsOnly && !VisitPreprocessorLast)\r
- if (visitPreprocessedEntitiesInRegion())\r
- return; // visitation break.\r
-\r
- visitDeclsFromFileRegion(File, Offset, Length);\r
-\r
- if (!VisitDeclsOnly && VisitPreprocessorLast)\r
- visitPreprocessedEntitiesInRegion();\r
-}\r
-\r
-static bool isInLexicalContext(Decl *D, DeclContext *DC) {\r
- if (!DC)\r
- return false;\r
-\r
- for (DeclContext *DeclDC = D->getLexicalDeclContext();\r
- DeclDC; DeclDC = DeclDC->getLexicalParent()) {\r
- if (DeclDC == DC)\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-void CursorVisitor::visitDeclsFromFileRegion(FileID File,\r
- unsigned Offset, unsigned Length) {\r
- ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData);\r
- SourceManager &SM = Unit->getSourceManager();\r
- SourceRange Range = RegionOfInterest;\r
-\r
- SmallVector<Decl *, 16> Decls;\r
- Unit->findFileRegionDecls(File, Offset, Length, Decls);\r
-\r
- // If we didn't find any file level decls for the file, try looking at the\r
- // file that it was included from.\r
- while (Decls.empty() || Decls.front()->isTopLevelDeclInObjCContainer()) {\r
- bool Invalid = false;\r
- const SrcMgr::SLocEntry &SLEntry = SM.getSLocEntry(File, &Invalid);\r
- if (Invalid)\r
- return;\r
-\r
- SourceLocation Outer;\r
- if (SLEntry.isFile())\r
- Outer = SLEntry.getFile().getIncludeLoc();\r
- else\r
- Outer = SLEntry.getExpansion().getExpansionLocStart();\r
- if (Outer.isInvalid())\r
- return;\r
-\r
- llvm::tie(File, Offset) = SM.getDecomposedExpansionLoc(Outer);\r
- Length = 0;\r
- Unit->findFileRegionDecls(File, Offset, Length, Decls);\r
- }\r
-\r
- assert(!Decls.empty());\r
-\r
- bool VisitedAtLeastOnce = false;\r
- DeclContext *CurDC = 0;\r
- SmallVector<Decl *, 16>::iterator DIt = Decls.begin();\r
- for (SmallVector<Decl *, 16>::iterator DE = Decls.end(); DIt != DE; ++DIt) {\r
- Decl *D = *DIt;\r
- if (D->getSourceRange().isInvalid())\r
- continue;\r
-\r
- if (isInLexicalContext(D, CurDC))\r
- continue;\r
-\r
- CurDC = dyn_cast<DeclContext>(D);\r
-\r
- if (TagDecl *TD = dyn_cast<TagDecl>(D))\r
- if (!TD->isFreeStanding())\r
- continue;\r
-\r
- RangeComparisonResult CompRes = RangeCompare(SM, D->getSourceRange(),Range);\r
- if (CompRes == RangeBefore)\r
- continue;\r
- if (CompRes == RangeAfter)\r
- break;\r
-\r
- assert(CompRes == RangeOverlap);\r
- VisitedAtLeastOnce = true;\r
-\r
- if (isa<ObjCContainerDecl>(D)) {\r
- FileDI_current = &DIt;\r
- FileDE_current = DE;\r
- } else {\r
- FileDI_current = 0;\r
- }\r
-\r
- if (Visit(MakeCXCursor(D, TU, Range), /*CheckedRegionOfInterest=*/true))\r
- break;\r
- }\r
-\r
- if (VisitedAtLeastOnce)\r
- return;\r
-\r
- // No Decls overlapped with the range. Move up the lexical context until there\r
- // is a context that contains the range or we reach the translation unit\r
- // level.\r
- DeclContext *DC = DIt == Decls.begin() ? (*DIt)->getLexicalDeclContext()\r
- : (*(DIt-1))->getLexicalDeclContext();\r
-\r
- while (DC && !DC->isTranslationUnit()) {\r
- Decl *D = cast<Decl>(DC);\r
- SourceRange CurDeclRange = D->getSourceRange();\r
- if (CurDeclRange.isInvalid())\r
- break;\r
-\r
- if (RangeCompare(SM, CurDeclRange, Range) == RangeOverlap) {\r
- Visit(MakeCXCursor(D, TU, Range), /*CheckedRegionOfInterest=*/true);\r
- break;\r
- }\r
-\r
- DC = D->getLexicalDeclContext();\r
- }\r
-}\r
-\r
-bool CursorVisitor::visitPreprocessedEntitiesInRegion() {\r
- if (!AU->getPreprocessor().getPreprocessingRecord())\r
- return false;\r
-\r
- PreprocessingRecord &PPRec\r
- = *AU->getPreprocessor().getPreprocessingRecord();\r
- SourceManager &SM = AU->getSourceManager();\r
- \r
- if (RegionOfInterest.isValid()) {\r
- SourceRange MappedRange = AU->mapRangeToPreamble(RegionOfInterest);\r
- SourceLocation B = MappedRange.getBegin();\r
- SourceLocation E = MappedRange.getEnd();\r
-\r
- if (AU->isInPreambleFileID(B)) {\r
- if (SM.isLoadedSourceLocation(E))\r
- return visitPreprocessedEntitiesInRange(SourceRange(B, E),\r
- PPRec, *this);\r
-\r
- // Beginning of range lies in the preamble but it also extends beyond\r
- // it into the main file. Split the range into 2 parts, one covering\r
- // the preamble and another covering the main file. This allows subsequent\r
- // calls to visitPreprocessedEntitiesInRange to accept a source range that\r
- // lies in the same FileID, allowing it to skip preprocessed entities that\r
- // do not come from the same FileID.\r
- bool breaked =\r
- visitPreprocessedEntitiesInRange(\r
- SourceRange(B, AU->getEndOfPreambleFileID()),\r
- PPRec, *this);\r
- if (breaked) return true;\r
- return visitPreprocessedEntitiesInRange(\r
- SourceRange(AU->getStartOfMainFileID(), E),\r
- PPRec, *this);\r
- }\r
-\r
- return visitPreprocessedEntitiesInRange(SourceRange(B, E), PPRec, *this);\r
- }\r
-\r
- bool OnlyLocalDecls\r
- = !AU->isMainFileAST() && AU->getOnlyLocalDecls(); \r
- \r
- if (OnlyLocalDecls)\r
- return visitPreprocessedEntities(PPRec.local_begin(), PPRec.local_end(),\r
- PPRec);\r
-\r
- return visitPreprocessedEntities(PPRec.begin(), PPRec.end(), PPRec);\r
-}\r
-\r
-template<typename InputIterator>\r
-bool CursorVisitor::visitPreprocessedEntities(InputIterator First,\r
- InputIterator Last,\r
- PreprocessingRecord &PPRec,\r
- FileID FID) {\r
- for (; First != Last; ++First) {\r
- if (!FID.isInvalid() && !PPRec.isEntityInFileID(First, FID))\r
- continue;\r
-\r
- PreprocessedEntity *PPE = *First;\r
- if (MacroExpansion *ME = dyn_cast<MacroExpansion>(PPE)) {\r
- if (Visit(MakeMacroExpansionCursor(ME, TU)))\r
- return true;\r
- \r
- continue;\r
- }\r
- \r
- if (MacroDefinition *MD = dyn_cast<MacroDefinition>(PPE)) {\r
- if (Visit(MakeMacroDefinitionCursor(MD, TU)))\r
- return true;\r
- \r
- continue;\r
- }\r
- \r
- if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) {\r
- if (Visit(MakeInclusionDirectiveCursor(ID, TU)))\r
- return true;\r
- \r
- continue;\r
- }\r
- }\r
-\r
- return false;\r
-}\r
-\r
-/// \brief Visit the children of the given cursor.\r
-/// \r
-/// \returns true if the visitation should be aborted, false if it\r
-/// should continue.\r
-bool CursorVisitor::VisitChildren(CXCursor Cursor) {\r
- if (clang_isReference(Cursor.kind) && \r
- Cursor.kind != CXCursor_CXXBaseSpecifier) {\r
- // By definition, references have no children.\r
- return false;\r
- }\r
-\r
- // Set the Parent field to Cursor, then back to its old value once we're\r
- // done.\r
- SetParentRAII SetParent(Parent, StmtParent, Cursor);\r
-\r
- if (clang_isDeclaration(Cursor.kind)) {\r
- Decl *D = getCursorDecl(Cursor);\r
- if (!D)\r
- return false;\r
-\r
- return VisitAttributes(D) || Visit(D);\r
- }\r
-\r
- if (clang_isStatement(Cursor.kind)) {\r
- if (Stmt *S = getCursorStmt(Cursor))\r
- return Visit(S);\r
-\r
- return false;\r
- }\r
-\r
- if (clang_isExpression(Cursor.kind)) {\r
- if (Expr *E = getCursorExpr(Cursor))\r
- return Visit(E);\r
-\r
- return false;\r
- }\r
-\r
- if (clang_isTranslationUnit(Cursor.kind)) {\r
- CXTranslationUnit tu = getCursorTU(Cursor);\r
- ASTUnit *CXXUnit = static_cast<ASTUnit*>(tu->TUData);\r
- \r
- int VisitOrder[2] = { VisitPreprocessorLast, !VisitPreprocessorLast };\r
- for (unsigned I = 0; I != 2; ++I) {\r
- if (VisitOrder[I]) {\r
- if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&\r
- RegionOfInterest.isInvalid()) {\r
- for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),\r
- TLEnd = CXXUnit->top_level_end();\r
- TL != TLEnd; ++TL) {\r
- if (Visit(MakeCXCursor(*TL, tu, RegionOfInterest), true))\r
- return true;\r
- }\r
- } else if (VisitDeclContext(\r
- CXXUnit->getASTContext().getTranslationUnitDecl()))\r
- return true;\r
- continue;\r
- }\r
-\r
- // Walk the preprocessing record.\r
- if (CXXUnit->getPreprocessor().getPreprocessingRecord())\r
- visitPreprocessedEntitiesInRegion();\r
- }\r
- \r
- return false;\r
- }\r
-\r
- if (Cursor.kind == CXCursor_CXXBaseSpecifier) {\r
- if (CXXBaseSpecifier *Base = getCursorCXXBaseSpecifier(Cursor)) {\r
- if (TypeSourceInfo *BaseTSInfo = Base->getTypeSourceInfo()) {\r
- return Visit(BaseTSInfo->getTypeLoc());\r
- }\r
- }\r
- }\r
-\r
- if (Cursor.kind == CXCursor_IBOutletCollectionAttr) {\r
- IBOutletCollectionAttr *A =\r
- cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(Cursor));\r
- if (const ObjCInterfaceType *InterT = A->getInterface()->getAs<ObjCInterfaceType>())\r
- return Visit(cxcursor::MakeCursorObjCClassRef(InterT->getInterface(),\r
- A->getInterfaceLoc(), TU));\r
- }\r
-\r
- // Nothing to visit at the moment.\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitBlockDecl(BlockDecl *B) {\r
- if (TypeSourceInfo *TSInfo = B->getSignatureAsWritten())\r
- if (Visit(TSInfo->getTypeLoc()))\r
- return true;\r
-\r
- if (Stmt *Body = B->getBody())\r
- return Visit(MakeCXCursor(Body, StmtParent, TU, RegionOfInterest));\r
-\r
- return false;\r
-}\r
-\r
-llvm::Optional<bool> CursorVisitor::shouldVisitCursor(CXCursor Cursor) {\r
- if (RegionOfInterest.isValid()) {\r
- SourceRange Range = getFullCursorExtent(Cursor, AU->getSourceManager());\r
- if (Range.isInvalid())\r
- return llvm::Optional<bool>();\r
- \r
- switch (CompareRegionOfInterest(Range)) {\r
- case RangeBefore:\r
- // This declaration comes before the region of interest; skip it.\r
- return llvm::Optional<bool>();\r
-\r
- case RangeAfter:\r
- // This declaration comes after the region of interest; we're done.\r
- return false;\r
-\r
- case RangeOverlap:\r
- // This declaration overlaps the region of interest; visit it.\r
- break;\r
- }\r
- }\r
- return true;\r
-}\r
-\r
-bool CursorVisitor::VisitDeclContext(DeclContext *DC) {\r
- DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();\r
-\r
- // FIXME: Eventually remove. This part of a hack to support proper\r
- // iteration over all Decls contained lexically within an ObjC container.\r
- SaveAndRestore<DeclContext::decl_iterator*> DI_saved(DI_current, &I);\r
- SaveAndRestore<DeclContext::decl_iterator> DE_saved(DE_current, E);\r
-\r
- for ( ; I != E; ++I) {\r
- Decl *D = *I;\r
- if (D->getLexicalDeclContext() != DC)\r
- continue;\r
- CXCursor Cursor = MakeCXCursor(D, TU, RegionOfInterest);\r
-\r
- // Ignore synthesized ivars here, otherwise if we have something like:\r
- // @synthesize prop = _prop;\r
- // and '_prop' is not declared, we will encounter a '_prop' ivar before\r
- // encountering the 'prop' synthesize declaration and we will think that\r
- // we passed the region-of-interest.\r
- if (ObjCIvarDecl *ivarD = dyn_cast<ObjCIvarDecl>(D)) {\r
- if (ivarD->getSynthesize())\r
- continue;\r
- }\r
-\r
- // FIXME: ObjCClassRef/ObjCProtocolRef for forward class/protocol\r
- // declarations is a mismatch with the compiler semantics.\r
- if (Cursor.kind == CXCursor_ObjCInterfaceDecl) {\r
- ObjCInterfaceDecl *ID = cast<ObjCInterfaceDecl>(D);\r
- if (!ID->isThisDeclarationADefinition())\r
- Cursor = MakeCursorObjCClassRef(ID, ID->getLocation(), TU);\r
-\r
- } else if (Cursor.kind == CXCursor_ObjCProtocolDecl) {\r
- ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D);\r
- if (!PD->isThisDeclarationADefinition())\r
- Cursor = MakeCursorObjCProtocolRef(PD, PD->getLocation(), TU);\r
- }\r
-\r
- const llvm::Optional<bool> &V = shouldVisitCursor(Cursor);\r
- if (!V.hasValue())\r
- continue;\r
- if (!V.getValue())\r
- return false;\r
- if (Visit(Cursor, true))\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {\r
- llvm_unreachable("Translation units are visited directly by Visit()");\r
-}\r
-\r
-bool CursorVisitor::VisitTypeAliasDecl(TypeAliasDecl *D) {\r
- if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())\r
- return Visit(TSInfo->getTypeLoc());\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitTypedefDecl(TypedefDecl *D) {\r
- if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())\r
- return Visit(TSInfo->getTypeLoc());\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitTagDecl(TagDecl *D) {\r
- return VisitDeclContext(D);\r
-}\r
-\r
-bool CursorVisitor::VisitClassTemplateSpecializationDecl(\r
- ClassTemplateSpecializationDecl *D) {\r
- bool ShouldVisitBody = false;\r
- switch (D->getSpecializationKind()) {\r
- case TSK_Undeclared:\r
- case TSK_ImplicitInstantiation:\r
- // Nothing to visit\r
- return false;\r
- \r
- case TSK_ExplicitInstantiationDeclaration:\r
- case TSK_ExplicitInstantiationDefinition:\r
- break;\r
- \r
- case TSK_ExplicitSpecialization:\r
- ShouldVisitBody = true;\r
- break;\r
- }\r
- \r
- // Visit the template arguments used in the specialization.\r
- if (TypeSourceInfo *SpecType = D->getTypeAsWritten()) {\r
- TypeLoc TL = SpecType->getTypeLoc();\r
- if (TemplateSpecializationTypeLoc *TSTLoc\r
- = dyn_cast<TemplateSpecializationTypeLoc>(&TL)) {\r
- for (unsigned I = 0, N = TSTLoc->getNumArgs(); I != N; ++I)\r
- if (VisitTemplateArgumentLoc(TSTLoc->getArgLoc(I)))\r
- return true;\r
- }\r
- }\r
- \r
- if (ShouldVisitBody && VisitCXXRecordDecl(D))\r
- return true;\r
- \r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitClassTemplatePartialSpecializationDecl(\r
- ClassTemplatePartialSpecializationDecl *D) {\r
- // FIXME: Visit the "outer" template parameter lists on the TagDecl\r
- // before visiting these template parameters.\r
- if (VisitTemplateParameters(D->getTemplateParameters()))\r
- return true;\r
-\r
- // Visit the partial specialization arguments.\r
- const TemplateArgumentLoc *TemplateArgs = D->getTemplateArgsAsWritten();\r
- for (unsigned I = 0, N = D->getNumTemplateArgsAsWritten(); I != N; ++I)\r
- if (VisitTemplateArgumentLoc(TemplateArgs[I]))\r
- return true;\r
- \r
- return VisitCXXRecordDecl(D);\r
-}\r
-\r
-bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {\r
- // Visit the default argument.\r
- if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())\r
- if (TypeSourceInfo *DefArg = D->getDefaultArgumentInfo())\r
- if (Visit(DefArg->getTypeLoc()))\r
- return true;\r
- \r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {\r
- if (Expr *Init = D->getInitExpr())\r
- return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {\r
- if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())\r
- if (Visit(TSInfo->getTypeLoc()))\r
- return true;\r
-\r
- // Visit the nested-name-specifier, if present.\r
- if (NestedNameSpecifierLoc QualifierLoc = DD->getQualifierLoc())\r
- if (VisitNestedNameSpecifierLoc(QualifierLoc))\r
- return true;\r
-\r
- return false;\r
-}\r
-\r
-/// \brief Compare two base or member initializers based on their source order.\r
-static int CompareCXXCtorInitializers(const void* Xp, const void *Yp) {\r
- CXXCtorInitializer const * const *X\r
- = static_cast<CXXCtorInitializer const * const *>(Xp);\r
- CXXCtorInitializer const * const *Y\r
- = static_cast<CXXCtorInitializer const * const *>(Yp);\r
- \r
- if ((*X)->getSourceOrder() < (*Y)->getSourceOrder())\r
- return -1;\r
- else if ((*X)->getSourceOrder() > (*Y)->getSourceOrder())\r
- return 1;\r
- else\r
- return 0;\r
-}\r
-\r
-bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {\r
- if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {\r
- // Visit the function declaration's syntactic components in the order\r
- // written. This requires a bit of work.\r
- TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();\r
- FunctionTypeLoc *FTL = dyn_cast<FunctionTypeLoc>(&TL);\r
- \r
- // If we have a function declared directly (without the use of a typedef),\r
- // visit just the return type. Otherwise, just visit the function's type\r
- // now.\r
- if ((FTL && !isa<CXXConversionDecl>(ND) && Visit(FTL->getResultLoc())) ||\r
- (!FTL && Visit(TL)))\r
- return true;\r
- \r
- // Visit the nested-name-specifier, if present.\r
- if (NestedNameSpecifierLoc QualifierLoc = ND->getQualifierLoc())\r
- if (VisitNestedNameSpecifierLoc(QualifierLoc))\r
- return true;\r
- \r
- // Visit the declaration name.\r
- if (VisitDeclarationNameInfo(ND->getNameInfo()))\r
- return true;\r
- \r
- // FIXME: Visit explicitly-specified template arguments!\r
- \r
- // Visit the function parameters, if we have a function type.\r
- if (FTL && VisitFunctionTypeLoc(*FTL, true))\r
- return true;\r
- \r
- // FIXME: Attributes?\r
- }\r
- \r
- if (ND->doesThisDeclarationHaveABody() && !ND->isLateTemplateParsed()) {\r
- if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ND)) {\r
- // Find the initializers that were written in the source.\r
- SmallVector<CXXCtorInitializer *, 4> WrittenInits;\r
- for (CXXConstructorDecl::init_iterator I = Constructor->init_begin(),\r
- IEnd = Constructor->init_end();\r
- I != IEnd; ++I) {\r
- if (!(*I)->isWritten())\r
- continue;\r
- \r
- WrittenInits.push_back(*I);\r
- }\r
- \r
- // Sort the initializers in source order\r
- llvm::array_pod_sort(WrittenInits.begin(), WrittenInits.end(),\r
- &CompareCXXCtorInitializers);\r
- \r
- // Visit the initializers in source order\r
- for (unsigned I = 0, N = WrittenInits.size(); I != N; ++I) {\r
- CXXCtorInitializer *Init = WrittenInits[I];\r
- if (Init->isAnyMemberInitializer()) {\r
- if (Visit(MakeCursorMemberRef(Init->getAnyMember(),\r
- Init->getMemberLocation(), TU)))\r
- return true;\r
- } else if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) {\r
- if (Visit(TInfo->getTypeLoc()))\r
- return true;\r
- }\r
- \r
- // Visit the initializer value.\r
- if (Expr *Initializer = Init->getInit())\r
- if (Visit(MakeCXCursor(Initializer, ND, TU, RegionOfInterest)))\r
- return true;\r
- } \r
- }\r
- \r
- if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest)))\r
- return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitFieldDecl(FieldDecl *D) {\r
- if (VisitDeclaratorDecl(D))\r
- return true;\r
-\r
- if (Expr *BitWidth = D->getBitWidth())\r
- return Visit(MakeCXCursor(BitWidth, StmtParent, TU, RegionOfInterest));\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitVarDecl(VarDecl *D) {\r
- if (VisitDeclaratorDecl(D))\r
- return true;\r
-\r
- if (Expr *Init = D->getInit())\r
- return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {\r
- if (VisitDeclaratorDecl(D))\r
- return true;\r
- \r
- if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())\r
- if (Expr *DefArg = D->getDefaultArgument())\r
- return Visit(MakeCXCursor(DefArg, StmtParent, TU, RegionOfInterest));\r
- \r
- return false; \r
-}\r
-\r
-bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {\r
- // FIXME: Visit the "outer" template parameter lists on the FunctionDecl\r
- // before visiting these template parameters.\r
- if (VisitTemplateParameters(D->getTemplateParameters()))\r
- return true;\r
- \r
- return VisitFunctionDecl(D->getTemplatedDecl());\r
-}\r
-\r
-bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) {\r
- // FIXME: Visit the "outer" template parameter lists on the TagDecl\r
- // before visiting these template parameters.\r
- if (VisitTemplateParameters(D->getTemplateParameters()))\r
- return true;\r
- \r
- return VisitCXXRecordDecl(D->getTemplatedDecl());\r
-}\r
-\r
-bool CursorVisitor::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {\r
- if (VisitTemplateParameters(D->getTemplateParameters()))\r
- return true;\r
- \r
- if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited() &&\r
- VisitTemplateArgumentLoc(D->getDefaultArgument()))\r
- return true;\r
- \r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {\r
- if (TypeSourceInfo *TSInfo = ND->getResultTypeSourceInfo())\r
- if (Visit(TSInfo->getTypeLoc()))\r
- return true;\r
-\r
- for (ObjCMethodDecl::param_iterator P = ND->param_begin(),\r
- PEnd = ND->param_end();\r
- P != PEnd; ++P) {\r
- if (Visit(MakeCXCursor(*P, TU, RegionOfInterest)))\r
- return true;\r
- }\r
-\r
- if (ND->isThisDeclarationADefinition() &&\r
- Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest)))\r
- return true;\r
-\r
- return false;\r
-}\r
-\r
-template <typename DeclIt>\r
-static void addRangedDeclsInContainer(DeclIt *DI_current, DeclIt DE_current,\r
- SourceManager &SM, SourceLocation EndLoc,\r
- SmallVectorImpl<Decl *> &Decls) {\r
- DeclIt next = *DI_current;\r
- while (++next != DE_current) {\r
- Decl *D_next = *next;\r
- if (!D_next)\r
- break;\r
- SourceLocation L = D_next->getLocStart();\r
- if (!L.isValid())\r
- break;\r
- if (SM.isBeforeInTranslationUnit(L, EndLoc)) {\r
- *DI_current = next;\r
- Decls.push_back(D_next);\r
- continue;\r
- }\r
- break;\r
- }\r
-}\r
-\r
-namespace {\r
- struct ContainerDeclsSort {\r
- SourceManager &SM;\r
- ContainerDeclsSort(SourceManager &sm) : SM(sm) {}\r
- bool operator()(Decl *A, Decl *B) {\r
- SourceLocation L_A = A->getLocStart();\r
- SourceLocation L_B = B->getLocStart();\r
- assert(L_A.isValid() && L_B.isValid());\r
- return SM.isBeforeInTranslationUnit(L_A, L_B);\r
- }\r
- };\r
-}\r
-\r
-bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {\r
- // FIXME: Eventually convert back to just 'VisitDeclContext()'. Essentially\r
- // an @implementation can lexically contain Decls that are not properly\r
- // nested in the AST. When we identify such cases, we need to retrofit\r
- // this nesting here.\r
- if (!DI_current && !FileDI_current)\r
- return VisitDeclContext(D);\r
-\r
- // Scan the Decls that immediately come after the container\r
- // in the current DeclContext. If any fall within the\r
- // container's lexical region, stash them into a vector\r
- // for later processing.\r
- SmallVector<Decl *, 24> DeclsInContainer;\r
- SourceLocation EndLoc = D->getSourceRange().getEnd();\r
- SourceManager &SM = AU->getSourceManager();\r
- if (EndLoc.isValid()) {\r
- if (DI_current) {\r
- addRangedDeclsInContainer(DI_current, DE_current, SM, EndLoc,\r
- DeclsInContainer);\r
- } else {\r
- addRangedDeclsInContainer(FileDI_current, FileDE_current, SM, EndLoc,\r
- DeclsInContainer);\r
- }\r
- }\r
-\r
- // The common case.\r
- if (DeclsInContainer.empty())\r
- return VisitDeclContext(D);\r
-\r
- // Get all the Decls in the DeclContext, and sort them with the\r
- // additional ones we've collected. Then visit them.\r
- for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();\r
- I!=E; ++I) {\r
- Decl *subDecl = *I;\r
- if (!subDecl || subDecl->getLexicalDeclContext() != D ||\r
- subDecl->getLocStart().isInvalid())\r
- continue;\r
- DeclsInContainer.push_back(subDecl);\r
- }\r
-\r
- // Now sort the Decls so that they appear in lexical order.\r
- std::sort(DeclsInContainer.begin(), DeclsInContainer.end(),\r
- ContainerDeclsSort(SM));\r
-\r
- // Now visit the decls.\r
- for (SmallVectorImpl<Decl*>::iterator I = DeclsInContainer.begin(),\r
- E = DeclsInContainer.end(); I != E; ++I) {\r
- CXCursor Cursor = MakeCXCursor(*I, TU, RegionOfInterest);\r
- const llvm::Optional<bool> &V = shouldVisitCursor(Cursor);\r
- if (!V.hasValue())\r
- continue;\r
- if (!V.getValue())\r
- return false;\r
- if (Visit(Cursor, true))\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {\r
- if (Visit(MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation(),\r
- TU)))\r
- return true;\r
-\r
- ObjCCategoryDecl::protocol_loc_iterator PL = ND->protocol_loc_begin();\r
- for (ObjCCategoryDecl::protocol_iterator I = ND->protocol_begin(),\r
- E = ND->protocol_end(); I != E; ++I, ++PL)\r
- if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))\r
- return true;\r
-\r
- return VisitObjCContainerDecl(ND);\r
-}\r
-\r
-bool CursorVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {\r
- if (!PID->isThisDeclarationADefinition())\r
- return Visit(MakeCursorObjCProtocolRef(PID, PID->getLocation(), TU));\r
- \r
- ObjCProtocolDecl::protocol_loc_iterator PL = PID->protocol_loc_begin();\r
- for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),\r
- E = PID->protocol_end(); I != E; ++I, ++PL)\r
- if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))\r
- return true;\r
-\r
- return VisitObjCContainerDecl(PID);\r
-}\r
-\r
-bool CursorVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *PD) {\r
- if (PD->getTypeSourceInfo() && Visit(PD->getTypeSourceInfo()->getTypeLoc()))\r
- return true;\r
-\r
- // FIXME: This implements a workaround with @property declarations also being\r
- // installed in the DeclContext for the @interface. Eventually this code\r
- // should be removed.\r
- ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(PD->getDeclContext());\r
- if (!CDecl || !CDecl->IsClassExtension())\r
- return false;\r
-\r
- ObjCInterfaceDecl *ID = CDecl->getClassInterface();\r
- if (!ID)\r
- return false;\r
-\r
- IdentifierInfo *PropertyId = PD->getIdentifier();\r
- ObjCPropertyDecl *prevDecl =\r
- ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(ID), PropertyId);\r
-\r
- if (!prevDecl)\r
- return false;\r
-\r
- // Visit synthesized methods since they will be skipped when visiting\r
- // the @interface.\r
- if (ObjCMethodDecl *MD = prevDecl->getGetterMethodDecl())\r
- if (MD->isPropertyAccessor() && MD->getLexicalDeclContext() == CDecl)\r
- if (Visit(MakeCXCursor(MD, TU, RegionOfInterest)))\r
- return true;\r
-\r
- if (ObjCMethodDecl *MD = prevDecl->getSetterMethodDecl())\r
- if (MD->isPropertyAccessor() && MD->getLexicalDeclContext() == CDecl)\r
- if (Visit(MakeCXCursor(MD, TU, RegionOfInterest)))\r
- return true;\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {\r
- if (!D->isThisDeclarationADefinition()) {\r
- // Forward declaration is treated like a reference.\r
- return Visit(MakeCursorObjCClassRef(D, D->getLocation(), TU));\r
- }\r
-\r
- // Issue callbacks for super class.\r
- if (D->getSuperClass() &&\r
- Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),\r
- D->getSuperClassLoc(),\r
- TU)))\r
- return true;\r
-\r
- ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin();\r
- for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(),\r
- E = D->protocol_end(); I != E; ++I, ++PL)\r
- if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))\r
- return true;\r
-\r
- return VisitObjCContainerDecl(D);\r
-}\r
-\r
-bool CursorVisitor::VisitObjCImplDecl(ObjCImplDecl *D) {\r
- return VisitObjCContainerDecl(D);\r
-}\r
-\r
-bool CursorVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {\r
- // 'ID' could be null when dealing with invalid code.\r
- if (ObjCInterfaceDecl *ID = D->getClassInterface())\r
- if (Visit(MakeCursorObjCClassRef(ID, D->getLocation(), TU)))\r
- return true;\r
-\r
- return VisitObjCImplDecl(D);\r
-}\r
-\r
-bool CursorVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {\r
-#if 0\r
- // Issue callbacks for super class.\r
- // FIXME: No source location information!\r
- if (D->getSuperClass() &&\r
- Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),\r
- D->getSuperClassLoc(),\r
- TU)))\r
- return true;\r
-#endif\r
-\r
- return VisitObjCImplDecl(D);\r
-}\r
-\r
-bool CursorVisitor::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD) {\r
- if (ObjCIvarDecl *Ivar = PD->getPropertyIvarDecl())\r
- if (PD->isIvarNameSpecified())\r
- return Visit(MakeCursorMemberRef(Ivar, PD->getPropertyIvarDeclLoc(), TU));\r
- \r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitNamespaceDecl(NamespaceDecl *D) {\r
- return VisitDeclContext(D);\r
-}\r
-\r
-bool CursorVisitor::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {\r
- // Visit nested-name-specifier.\r
- if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())\r
- if (VisitNestedNameSpecifierLoc(QualifierLoc))\r
- return true;\r
- \r
- return Visit(MakeCursorNamespaceRef(D->getAliasedNamespace(), \r
- D->getTargetNameLoc(), TU));\r
-}\r
-\r
-bool CursorVisitor::VisitUsingDecl(UsingDecl *D) {\r
- // Visit nested-name-specifier.\r
- if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) {\r
- if (VisitNestedNameSpecifierLoc(QualifierLoc))\r
- return true;\r
- }\r
- \r
- if (Visit(MakeCursorOverloadedDeclRef(D, D->getLocation(), TU)))\r
- return true;\r
- \r
- return VisitDeclarationNameInfo(D->getNameInfo());\r
-}\r
-\r
-bool CursorVisitor::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {\r
- // Visit nested-name-specifier.\r
- if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())\r
- if (VisitNestedNameSpecifierLoc(QualifierLoc))\r
- return true;\r
-\r
- return Visit(MakeCursorNamespaceRef(D->getNominatedNamespaceAsWritten(),\r
- D->getIdentLocation(), TU));\r
-}\r
-\r
-bool CursorVisitor::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {\r
- // Visit nested-name-specifier.\r
- if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) {\r
- if (VisitNestedNameSpecifierLoc(QualifierLoc))\r
- return true;\r
- }\r
-\r
- return VisitDeclarationNameInfo(D->getNameInfo());\r
-}\r
-\r
-bool CursorVisitor::VisitUnresolvedUsingTypenameDecl(\r
- UnresolvedUsingTypenameDecl *D) {\r
- // Visit nested-name-specifier.\r
- if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())\r
- if (VisitNestedNameSpecifierLoc(QualifierLoc))\r
- return true;\r
- \r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {\r
- switch (Name.getName().getNameKind()) {\r
- case clang::DeclarationName::Identifier:\r
- case clang::DeclarationName::CXXLiteralOperatorName:\r
- case clang::DeclarationName::CXXOperatorName:\r
- case clang::DeclarationName::CXXUsingDirective:\r
- return false;\r
- \r
- case clang::DeclarationName::CXXConstructorName:\r
- case clang::DeclarationName::CXXDestructorName:\r
- case clang::DeclarationName::CXXConversionFunctionName:\r
- if (TypeSourceInfo *TSInfo = Name.getNamedTypeInfo())\r
- return Visit(TSInfo->getTypeLoc());\r
- return false;\r
-\r
- case clang::DeclarationName::ObjCZeroArgSelector:\r
- case clang::DeclarationName::ObjCOneArgSelector:\r
- case clang::DeclarationName::ObjCMultiArgSelector:\r
- // FIXME: Per-identifier location info?\r
- return false;\r
- }\r
-\r
- llvm_unreachable("Invalid DeclarationName::Kind!");\r
-}\r
-\r
-bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS, \r
- SourceRange Range) {\r
- // FIXME: This whole routine is a hack to work around the lack of proper\r
- // source information in nested-name-specifiers (PR5791). Since we do have\r
- // a beginning source location, we can visit the first component of the\r
- // nested-name-specifier, if it's a single-token component.\r
- if (!NNS)\r
- return false;\r
- \r
- // Get the first component in the nested-name-specifier.\r
- while (NestedNameSpecifier *Prefix = NNS->getPrefix())\r
- NNS = Prefix;\r
- \r
- switch (NNS->getKind()) {\r
- case NestedNameSpecifier::Namespace:\r
- return Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(),\r
- TU));\r
-\r
- case NestedNameSpecifier::NamespaceAlias:\r
- return Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(), \r
- Range.getBegin(), TU));\r
-\r
- case NestedNameSpecifier::TypeSpec: {\r
- // If the type has a form where we know that the beginning of the source\r
- // range matches up with a reference cursor. Visit the appropriate reference\r
- // cursor.\r
- const Type *T = NNS->getAsType();\r
- if (const TypedefType *Typedef = dyn_cast<TypedefType>(T))\r
- return Visit(MakeCursorTypeRef(Typedef->getDecl(), Range.getBegin(), TU));\r
- if (const TagType *Tag = dyn_cast<TagType>(T))\r
- return Visit(MakeCursorTypeRef(Tag->getDecl(), Range.getBegin(), TU));\r
- if (const TemplateSpecializationType *TST\r
- = dyn_cast<TemplateSpecializationType>(T))\r
- return VisitTemplateName(TST->getTemplateName(), Range.getBegin());\r
- break;\r
- }\r
- \r
- case NestedNameSpecifier::TypeSpecWithTemplate:\r
- case NestedNameSpecifier::Global:\r
- case NestedNameSpecifier::Identifier:\r
- break; \r
- }\r
- \r
- return false;\r
-}\r
-\r
-bool \r
-CursorVisitor::VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) {\r
- SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;\r
- for (; Qualifier; Qualifier = Qualifier.getPrefix())\r
- Qualifiers.push_back(Qualifier);\r
- \r
- while (!Qualifiers.empty()) {\r
- NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();\r
- NestedNameSpecifier *NNS = Q.getNestedNameSpecifier();\r
- switch (NNS->getKind()) {\r
- case NestedNameSpecifier::Namespace:\r
- if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(), \r
- Q.getLocalBeginLoc(),\r
- TU)))\r
- return true;\r
- \r
- break;\r
- \r
- case NestedNameSpecifier::NamespaceAlias:\r
- if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(), \r
- Q.getLocalBeginLoc(),\r
- TU)))\r
- return true;\r
- \r
- break;\r
- \r
- case NestedNameSpecifier::TypeSpec:\r
- case NestedNameSpecifier::TypeSpecWithTemplate:\r
- if (Visit(Q.getTypeLoc()))\r
- return true;\r
- \r
- break;\r
- \r
- case NestedNameSpecifier::Global:\r
- case NestedNameSpecifier::Identifier:\r
- break; \r
- }\r
- }\r
- \r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitTemplateParameters(\r
- const TemplateParameterList *Params) {\r
- if (!Params)\r
- return false;\r
- \r
- for (TemplateParameterList::const_iterator P = Params->begin(),\r
- PEnd = Params->end();\r
- P != PEnd; ++P) {\r
- if (Visit(MakeCXCursor(*P, TU, RegionOfInterest)))\r
- return true;\r
- }\r
- \r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {\r
- switch (Name.getKind()) {\r
- case TemplateName::Template:\r
- return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU));\r
-\r
- case TemplateName::OverloadedTemplate:\r
- // Visit the overloaded template set.\r
- if (Visit(MakeCursorOverloadedDeclRef(Name, Loc, TU)))\r
- return true;\r
-\r
- return false;\r
-\r
- case TemplateName::DependentTemplate:\r
- // FIXME: Visit nested-name-specifier.\r
- return false;\r
- \r
- case TemplateName::QualifiedTemplate:\r
- // FIXME: Visit nested-name-specifier.\r
- return Visit(MakeCursorTemplateRef(\r
- Name.getAsQualifiedTemplateName()->getDecl(), \r
- Loc, TU));\r
-\r
- case TemplateName::SubstTemplateTemplateParm:\r
- return Visit(MakeCursorTemplateRef(\r
- Name.getAsSubstTemplateTemplateParm()->getParameter(),\r
- Loc, TU));\r
- \r
- case TemplateName::SubstTemplateTemplateParmPack:\r
- return Visit(MakeCursorTemplateRef(\r
- Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(),\r
- Loc, TU));\r
- }\r
-\r
- llvm_unreachable("Invalid TemplateName::Kind!");\r
-}\r
-\r
-bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {\r
- switch (TAL.getArgument().getKind()) {\r
- case TemplateArgument::Null:\r
- case TemplateArgument::Integral:\r
- case TemplateArgument::Pack:\r
- return false;\r
- \r
- case TemplateArgument::Type:\r
- if (TypeSourceInfo *TSInfo = TAL.getTypeSourceInfo())\r
- return Visit(TSInfo->getTypeLoc());\r
- return false;\r
- \r
- case TemplateArgument::Declaration:\r
- if (Expr *E = TAL.getSourceDeclExpression())\r
- return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));\r
- return false;\r
-\r
- case TemplateArgument::NullPtr:\r
- if (Expr *E = TAL.getSourceNullPtrExpression())\r
- return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));\r
- return false;\r
-\r
- case TemplateArgument::Expression:\r
- if (Expr *E = TAL.getSourceExpression())\r
- return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));\r
- return false;\r
- \r
- case TemplateArgument::Template:\r
- case TemplateArgument::TemplateExpansion:\r
- if (VisitNestedNameSpecifierLoc(TAL.getTemplateQualifierLoc()))\r
- return true;\r
- \r
- return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(), \r
- TAL.getTemplateNameLoc());\r
- }\r
-\r
- llvm_unreachable("Invalid TemplateArgument::Kind!");\r
-}\r
-\r
-bool CursorVisitor::VisitLinkageSpecDecl(LinkageSpecDecl *D) {\r
- return VisitDeclContext(D);\r
-}\r
-\r
-bool CursorVisitor::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {\r
- return Visit(TL.getUnqualifiedLoc());\r
-}\r
-\r
-bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {\r
- ASTContext &Context = AU->getASTContext();\r
-\r
- // Some builtin types (such as Objective-C's "id", "sel", and\r
- // "Class") have associated declarations. Create cursors for those.\r
- QualType VisitType;\r
- switch (TL.getTypePtr()->getKind()) {\r
-\r
- case BuiltinType::Void:\r
- case BuiltinType::NullPtr:\r
- case BuiltinType::Dependent:\r
- case BuiltinType::OCLImage1d:\r
- case BuiltinType::OCLImage1dArray:\r
- case BuiltinType::OCLImage1dBuffer:\r
- case BuiltinType::OCLImage2d:\r
- case BuiltinType::OCLImage2dArray:\r
- case BuiltinType::OCLImage3d:\r
-#define BUILTIN_TYPE(Id, SingletonId)\r
-#define SIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:\r
-#define UNSIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:\r
-#define FLOATING_TYPE(Id, SingletonId) case BuiltinType::Id:\r
-#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:\r
-#include "clang/AST/BuiltinTypes.def"\r
- break;\r
-\r
- case BuiltinType::ObjCId:\r
- VisitType = Context.getObjCIdType();\r
- break;\r
-\r
- case BuiltinType::ObjCClass:\r
- VisitType = Context.getObjCClassType();\r
- break;\r
-\r
- case BuiltinType::ObjCSel:\r
- VisitType = Context.getObjCSelType();\r
- break;\r
- }\r
-\r
- if (!VisitType.isNull()) {\r
- if (const TypedefType *Typedef = VisitType->getAs<TypedefType>())\r
- return Visit(MakeCursorTypeRef(Typedef->getDecl(), TL.getBuiltinLoc(),\r
- TU));\r
- }\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {\r
- return Visit(MakeCursorTypeRef(TL.getTypedefNameDecl(), TL.getNameLoc(), TU));\r
-}\r
-\r
-bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {\r
- return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));\r
-}\r
-\r
-bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {\r
- if (TL.isDefinition())\r
- return Visit(MakeCXCursor(TL.getDecl(), TU, RegionOfInterest));\r
-\r
- return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));\r
-}\r
-\r
-bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {\r
- return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));\r
-}\r
-\r
-bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {\r
- if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)))\r
- return true;\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {\r
- if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseLoc()))\r
- return true;\r
-\r
- for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {\r
- if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),\r
- TU)))\r
- return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {\r
- return Visit(TL.getPointeeLoc());\r
-}\r
-\r
-bool CursorVisitor::VisitParenTypeLoc(ParenTypeLoc TL) {\r
- return Visit(TL.getInnerLoc());\r
-}\r
-\r
-bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {\r
- return Visit(TL.getPointeeLoc());\r
-}\r
-\r
-bool CursorVisitor::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {\r
- return Visit(TL.getPointeeLoc());\r
-}\r
-\r
-bool CursorVisitor::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {\r
- return Visit(TL.getPointeeLoc());\r
-}\r
-\r
-bool CursorVisitor::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {\r
- return Visit(TL.getPointeeLoc());\r
-}\r
-\r
-bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {\r
- return Visit(TL.getPointeeLoc());\r
-}\r
-\r
-bool CursorVisitor::VisitAttributedTypeLoc(AttributedTypeLoc TL) {\r
- return Visit(TL.getModifiedLoc());\r
-}\r
-\r
-bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL, \r
- bool SkipResultType) {\r
- if (!SkipResultType && Visit(TL.getResultLoc()))\r
- return true;\r
-\r
- for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)\r
- if (Decl *D = TL.getArg(I))\r
- if (Visit(MakeCXCursor(D, TU, RegionOfInterest)))\r
- return true;\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {\r
- if (Visit(TL.getElementLoc()))\r
- return true;\r
-\r
- if (Expr *Size = TL.getSizeExpr())\r
- return Visit(MakeCXCursor(Size, StmtParent, TU, RegionOfInterest));\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitTemplateSpecializationTypeLoc(\r
- TemplateSpecializationTypeLoc TL) {\r
- // Visit the template name.\r
- if (VisitTemplateName(TL.getTypePtr()->getTemplateName(), \r
- TL.getTemplateNameLoc()))\r
- return true;\r
- \r
- // Visit the template arguments.\r
- for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)\r
- if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))\r
- return true;\r
- \r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {\r
- return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));\r
-}\r
-\r
-bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {\r
- if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())\r
- return Visit(TSInfo->getTypeLoc());\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {\r
- if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())\r
- return Visit(TSInfo->getTypeLoc());\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {\r
- if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))\r
- return true;\r
- \r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc(\r
- DependentTemplateSpecializationTypeLoc TL) {\r
- // Visit the nested-name-specifier, if there is one.\r
- if (TL.getQualifierLoc() &&\r
- VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))\r
- return true;\r
- \r
- // Visit the template arguments.\r
- for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)\r
- if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))\r
- return true;\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {\r
- if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))\r
- return true;\r
- \r
- return Visit(TL.getNamedTypeLoc());\r
-}\r
-\r
-bool CursorVisitor::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {\r
- return Visit(TL.getPatternLoc());\r
-}\r
-\r
-bool CursorVisitor::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {\r
- if (Expr *E = TL.getUnderlyingExpr())\r
- return Visit(MakeCXCursor(E, StmtParent, TU));\r
-\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {\r
- return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));\r
-}\r
-\r
-bool CursorVisitor::VisitAtomicTypeLoc(AtomicTypeLoc TL) {\r
- return Visit(TL.getValueLoc());\r
-}\r
-\r
-#define DEFAULT_TYPELOC_IMPL(CLASS, PARENT) \\r
-bool CursorVisitor::Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { \\r
- return Visit##PARENT##Loc(TL); \\r
-}\r
-\r
-DEFAULT_TYPELOC_IMPL(Complex, Type)\r
-DEFAULT_TYPELOC_IMPL(ConstantArray, ArrayType)\r
-DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType)\r
-DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType)\r
-DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType)\r
-DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type)\r
-DEFAULT_TYPELOC_IMPL(Vector, Type)\r
-DEFAULT_TYPELOC_IMPL(ExtVector, VectorType)\r
-DEFAULT_TYPELOC_IMPL(FunctionProto, FunctionType)\r
-DEFAULT_TYPELOC_IMPL(FunctionNoProto, FunctionType)\r
-DEFAULT_TYPELOC_IMPL(Record, TagType)\r
-DEFAULT_TYPELOC_IMPL(Enum, TagType)\r
-DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParm, Type)\r
-DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParmPack, Type)\r
-DEFAULT_TYPELOC_IMPL(Auto, Type)\r
-\r
-bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {\r
- // Visit the nested-name-specifier, if present.\r
- if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())\r
- if (VisitNestedNameSpecifierLoc(QualifierLoc))\r
- return true;\r
-\r
- if (D->isCompleteDefinition()) {\r
- for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),\r
- E = D->bases_end(); I != E; ++I) {\r
- if (Visit(cxcursor::MakeCursorCXXBaseSpecifier(I, TU)))\r
- return true;\r
- }\r
- }\r
-\r
- return VisitTagDecl(D);\r
-}\r
-\r
-bool CursorVisitor::VisitAttributes(Decl *D) {\r
- for (AttrVec::const_iterator i = D->attr_begin(), e = D->attr_end();\r
- i != e; ++i)\r
- if (Visit(MakeCXCursor(*i, D, TU)))\r
- return true;\r
-\r
- return false;\r
-}\r
-\r
-//===----------------------------------------------------------------------===//\r
-// Data-recursive visitor methods.\r
-//===----------------------------------------------------------------------===//\r
-\r
-namespace {\r
-#define DEF_JOB(NAME, DATA, KIND)\\r
-class NAME : public VisitorJob {\\r
-public:\\r
- NAME(DATA *d, CXCursor parent) : VisitorJob(parent, VisitorJob::KIND, d) {} \\r
- static bool classof(const VisitorJob *VJ) { return VJ->getKind() == KIND; }\\r
- DATA *get() const { return static_cast<DATA*>(data[0]); }\\r
-};\r
-\r
-DEF_JOB(StmtVisit, Stmt, StmtVisitKind)\r
-DEF_JOB(MemberExprParts, MemberExpr, MemberExprPartsKind)\r
-DEF_JOB(DeclRefExprParts, DeclRefExpr, DeclRefExprPartsKind)\r
-DEF_JOB(OverloadExprParts, OverloadExpr, OverloadExprPartsKind)\r
-DEF_JOB(ExplicitTemplateArgsVisit, ASTTemplateArgumentListInfo, \r
- ExplicitTemplateArgsVisitKind)\r
-DEF_JOB(SizeOfPackExprParts, SizeOfPackExpr, SizeOfPackExprPartsKind)\r
-DEF_JOB(LambdaExprParts, LambdaExpr, LambdaExprPartsKind)\r
-DEF_JOB(PostChildrenVisit, void, PostChildrenVisitKind)\r
-#undef DEF_JOB\r
-\r
-class DeclVisit : public VisitorJob {\r
-public:\r
- DeclVisit(Decl *d, CXCursor parent, bool isFirst) :\r
- VisitorJob(parent, VisitorJob::DeclVisitKind,\r
- d, isFirst ? (void*) 1 : (void*) 0) {}\r
- static bool classof(const VisitorJob *VJ) {\r
- return VJ->getKind() == DeclVisitKind;\r
- }\r
- Decl *get() const { return static_cast<Decl*>(data[0]); }\r
- bool isFirst() const { return data[1] ? true : false; }\r
-};\r
-class TypeLocVisit : public VisitorJob {\r
-public:\r
- TypeLocVisit(TypeLoc tl, CXCursor parent) :\r
- VisitorJob(parent, VisitorJob::TypeLocVisitKind,\r
- tl.getType().getAsOpaquePtr(), tl.getOpaqueData()) {}\r
-\r
- static bool classof(const VisitorJob *VJ) {\r
- return VJ->getKind() == TypeLocVisitKind;\r
- }\r
-\r
- TypeLoc get() const { \r
- QualType T = QualType::getFromOpaquePtr(data[0]);\r
- return TypeLoc(T, data[1]);\r
- }\r
-};\r
-\r
-class LabelRefVisit : public VisitorJob {\r
-public:\r
- LabelRefVisit(LabelDecl *LD, SourceLocation labelLoc, CXCursor parent)\r
- : VisitorJob(parent, VisitorJob::LabelRefVisitKind, LD,\r
- labelLoc.getPtrEncoding()) {}\r
- \r
- static bool classof(const VisitorJob *VJ) {\r
- return VJ->getKind() == VisitorJob::LabelRefVisitKind;\r
- }\r
- LabelDecl *get() const { return static_cast<LabelDecl*>(data[0]); }\r
- SourceLocation getLoc() const { \r
- return SourceLocation::getFromPtrEncoding(data[1]); }\r
-};\r
- \r
-class NestedNameSpecifierLocVisit : public VisitorJob {\r
-public:\r
- NestedNameSpecifierLocVisit(NestedNameSpecifierLoc Qualifier, CXCursor parent)\r
- : VisitorJob(parent, VisitorJob::NestedNameSpecifierLocVisitKind,\r
- Qualifier.getNestedNameSpecifier(),\r
- Qualifier.getOpaqueData()) { }\r
- \r
- static bool classof(const VisitorJob *VJ) {\r
- return VJ->getKind() == VisitorJob::NestedNameSpecifierLocVisitKind;\r
- }\r
- \r
- NestedNameSpecifierLoc get() const {\r
- return NestedNameSpecifierLoc(static_cast<NestedNameSpecifier*>(data[0]), \r
- data[1]);\r
- }\r
-};\r
- \r
-class DeclarationNameInfoVisit : public VisitorJob {\r
-public:\r
- DeclarationNameInfoVisit(Stmt *S, CXCursor parent)\r
- : VisitorJob(parent, VisitorJob::DeclarationNameInfoVisitKind, S) {}\r
- static bool classof(const VisitorJob *VJ) {\r
- return VJ->getKind() == VisitorJob::DeclarationNameInfoVisitKind;\r
- }\r
- DeclarationNameInfo get() const {\r
- Stmt *S = static_cast<Stmt*>(data[0]);\r
- switch (S->getStmtClass()) {\r
- default:\r
- llvm_unreachable("Unhandled Stmt");\r
- case clang::Stmt::MSDependentExistsStmtClass:\r
- return cast<MSDependentExistsStmt>(S)->getNameInfo();\r
- case Stmt::CXXDependentScopeMemberExprClass:\r
- return cast<CXXDependentScopeMemberExpr>(S)->getMemberNameInfo();\r
- case Stmt::DependentScopeDeclRefExprClass:\r
- return cast<DependentScopeDeclRefExpr>(S)->getNameInfo();\r
- }\r
- }\r
-};\r
-class MemberRefVisit : public VisitorJob {\r
-public:\r
- MemberRefVisit(FieldDecl *D, SourceLocation L, CXCursor parent)\r
- : VisitorJob(parent, VisitorJob::MemberRefVisitKind, D,\r
- L.getPtrEncoding()) {}\r
- static bool classof(const VisitorJob *VJ) {\r
- return VJ->getKind() == VisitorJob::MemberRefVisitKind;\r
- }\r
- FieldDecl *get() const {\r
- return static_cast<FieldDecl*>(data[0]);\r
- }\r
- SourceLocation getLoc() const {\r
- return SourceLocation::getFromRawEncoding((unsigned)(uintptr_t) data[1]);\r
- }\r
-};\r
-class EnqueueVisitor : public StmtVisitor<EnqueueVisitor, void> {\r
- VisitorWorkList &WL;\r
- CXCursor Parent;\r
-public:\r
- EnqueueVisitor(VisitorWorkList &wl, CXCursor parent)\r
- : WL(wl), Parent(parent) {}\r
-\r
- void VisitAddrLabelExpr(AddrLabelExpr *E);\r
- void VisitBlockExpr(BlockExpr *B);\r
- void VisitCompoundLiteralExpr(CompoundLiteralExpr *E);\r
- void VisitCompoundStmt(CompoundStmt *S);\r
- void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { /* Do nothing. */ }\r
- void VisitMSDependentExistsStmt(MSDependentExistsStmt *S);\r
- void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);\r
- void VisitCXXNewExpr(CXXNewExpr *E);\r
- void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);\r
- void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);\r
- void VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);\r
- void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);\r
- void VisitCXXTypeidExpr(CXXTypeidExpr *E);\r
- void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);\r
- void VisitCXXUuidofExpr(CXXUuidofExpr *E);\r
- void VisitCXXCatchStmt(CXXCatchStmt *S);\r
- void VisitDeclRefExpr(DeclRefExpr *D);\r
- void VisitDeclStmt(DeclStmt *S);\r
- void VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);\r
- void VisitDesignatedInitExpr(DesignatedInitExpr *E);\r
- void VisitExplicitCastExpr(ExplicitCastExpr *E);\r
- void VisitForStmt(ForStmt *FS);\r
- void VisitGotoStmt(GotoStmt *GS);\r
- void VisitIfStmt(IfStmt *If);\r
- void VisitInitListExpr(InitListExpr *IE);\r
- void VisitMemberExpr(MemberExpr *M);\r
- void VisitOffsetOfExpr(OffsetOfExpr *E);\r
- void VisitObjCEncodeExpr(ObjCEncodeExpr *E);\r
- void VisitObjCMessageExpr(ObjCMessageExpr *M);\r
- void VisitOverloadExpr(OverloadExpr *E);\r
- void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);\r
- void VisitStmt(Stmt *S);\r
- void VisitSwitchStmt(SwitchStmt *S);\r
- void VisitWhileStmt(WhileStmt *W);\r
- void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);\r
- void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);\r
- void VisitTypeTraitExpr(TypeTraitExpr *E);\r
- void VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);\r
- void VisitExpressionTraitExpr(ExpressionTraitExpr *E);\r
- void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U);\r
- void VisitVAArgExpr(VAArgExpr *E);\r
- void VisitSizeOfPackExpr(SizeOfPackExpr *E);\r
- void VisitPseudoObjectExpr(PseudoObjectExpr *E);\r
- void VisitOpaqueValueExpr(OpaqueValueExpr *E);\r
- void VisitLambdaExpr(LambdaExpr *E);\r
- \r
-private:\r
- void AddDeclarationNameInfo(Stmt *S);\r
- void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);\r
- void AddExplicitTemplateArgs(const ASTTemplateArgumentListInfo *A);\r
- void AddMemberRef(FieldDecl *D, SourceLocation L);\r
- void AddStmt(Stmt *S);\r
- void AddDecl(Decl *D, bool isFirst = true);\r
- void AddTypeLoc(TypeSourceInfo *TI);\r
- void EnqueueChildren(Stmt *S);\r
-};\r
-} // end anonyous namespace\r
-\r
-void EnqueueVisitor::AddDeclarationNameInfo(Stmt *S) {\r
- // 'S' should always be non-null, since it comes from the\r
- // statement we are visiting.\r
- WL.push_back(DeclarationNameInfoVisit(S, Parent));\r
-}\r
-\r
-void \r
-EnqueueVisitor::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) {\r
- if (Qualifier)\r
- WL.push_back(NestedNameSpecifierLocVisit(Qualifier, Parent));\r
-}\r
-\r
-void EnqueueVisitor::AddStmt(Stmt *S) {\r
- if (S)\r
- WL.push_back(StmtVisit(S, Parent));\r
-}\r
-void EnqueueVisitor::AddDecl(Decl *D, bool isFirst) {\r
- if (D)\r
- WL.push_back(DeclVisit(D, Parent, isFirst));\r
-}\r
-void EnqueueVisitor::\r
- AddExplicitTemplateArgs(const ASTTemplateArgumentListInfo *A) {\r
- if (A)\r
- WL.push_back(ExplicitTemplateArgsVisit(\r
- const_cast<ASTTemplateArgumentListInfo*>(A), Parent));\r
-}\r
-void EnqueueVisitor::AddMemberRef(FieldDecl *D, SourceLocation L) {\r
- if (D)\r
- WL.push_back(MemberRefVisit(D, L, Parent));\r
-}\r
-void EnqueueVisitor::AddTypeLoc(TypeSourceInfo *TI) {\r
- if (TI)\r
- WL.push_back(TypeLocVisit(TI->getTypeLoc(), Parent));\r
- }\r
-void EnqueueVisitor::EnqueueChildren(Stmt *S) {\r
- unsigned size = WL.size();\r
- for (Stmt::child_range Child = S->children(); Child; ++Child) {\r
- AddStmt(*Child);\r
- }\r
- if (size == WL.size())\r
- return;\r
- // Now reverse the entries we just added. This will match the DFS\r
- // ordering performed by the worklist.\r
- VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();\r
- std::reverse(I, E);\r
-}\r
-void EnqueueVisitor::VisitAddrLabelExpr(AddrLabelExpr *E) {\r
- WL.push_back(LabelRefVisit(E->getLabel(), E->getLabelLoc(), Parent));\r
-}\r
-void EnqueueVisitor::VisitBlockExpr(BlockExpr *B) {\r
- AddDecl(B->getBlockDecl());\r
-}\r
-void EnqueueVisitor::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {\r
- EnqueueChildren(E);\r
- AddTypeLoc(E->getTypeSourceInfo());\r
-}\r
-void EnqueueVisitor::VisitCompoundStmt(CompoundStmt *S) {\r
- for (CompoundStmt::reverse_body_iterator I = S->body_rbegin(),\r
- E = S->body_rend(); I != E; ++I) {\r
- AddStmt(*I);\r
- }\r
-}\r
-void EnqueueVisitor::\r
-VisitMSDependentExistsStmt(MSDependentExistsStmt *S) {\r
- AddStmt(S->getSubStmt());\r
- AddDeclarationNameInfo(S);\r
- if (NestedNameSpecifierLoc QualifierLoc = S->getQualifierLoc())\r
- AddNestedNameSpecifierLoc(QualifierLoc);\r
-}\r
-\r
-void EnqueueVisitor::\r
-VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {\r
- AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());\r
- AddDeclarationNameInfo(E);\r
- if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())\r
- AddNestedNameSpecifierLoc(QualifierLoc);\r
- if (!E->isImplicitAccess())\r
- AddStmt(E->getBase());\r
-}\r
-void EnqueueVisitor::VisitCXXNewExpr(CXXNewExpr *E) {\r
- // Enqueue the initializer , if any.\r
- AddStmt(E->getInitializer());\r
- // Enqueue the array size, if any.\r
- AddStmt(E->getArraySize());\r
- // Enqueue the allocated type.\r
- AddTypeLoc(E->getAllocatedTypeSourceInfo());\r
- // Enqueue the placement arguments.\r
- for (unsigned I = E->getNumPlacementArgs(); I > 0; --I)\r
- AddStmt(E->getPlacementArg(I-1));\r
-}\r
-void EnqueueVisitor::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {\r
- for (unsigned I = CE->getNumArgs(); I > 1 /* Yes, this is 1 */; --I)\r
- AddStmt(CE->getArg(I-1));\r
- AddStmt(CE->getCallee());\r
- AddStmt(CE->getArg(0));\r
-}\r
-void EnqueueVisitor::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {\r
- // Visit the name of the type being destroyed.\r
- AddTypeLoc(E->getDestroyedTypeInfo());\r
- // Visit the scope type that looks disturbingly like the nested-name-specifier\r
- // but isn't.\r
- AddTypeLoc(E->getScopeTypeInfo());\r
- // Visit the nested-name-specifier.\r
- if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())\r
- AddNestedNameSpecifierLoc(QualifierLoc);\r
- // Visit base expression.\r
- AddStmt(E->getBase());\r
-}\r
-void EnqueueVisitor::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {\r
- AddTypeLoc(E->getTypeSourceInfo());\r
-}\r
-void EnqueueVisitor::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {\r
- EnqueueChildren(E);\r
- AddTypeLoc(E->getTypeSourceInfo());\r
-}\r
-void EnqueueVisitor::VisitCXXTypeidExpr(CXXTypeidExpr *E) {\r
- EnqueueChildren(E);\r
- if (E->isTypeOperand())\r
- AddTypeLoc(E->getTypeOperandSourceInfo());\r
-}\r
-\r
-void EnqueueVisitor::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr \r
- *E) {\r
- EnqueueChildren(E);\r
- AddTypeLoc(E->getTypeSourceInfo());\r
-}\r
-void EnqueueVisitor::VisitCXXUuidofExpr(CXXUuidofExpr *E) {\r
- EnqueueChildren(E);\r
- if (E->isTypeOperand())\r
- AddTypeLoc(E->getTypeOperandSourceInfo());\r
-}\r
-\r
-void EnqueueVisitor::VisitCXXCatchStmt(CXXCatchStmt *S) {\r
- EnqueueChildren(S);\r
- AddDecl(S->getExceptionDecl());\r
-}\r
-\r
-void EnqueueVisitor::VisitDeclRefExpr(DeclRefExpr *DR) {\r
- if (DR->hasExplicitTemplateArgs()) {\r
- AddExplicitTemplateArgs(&DR->getExplicitTemplateArgs());\r
- }\r
- WL.push_back(DeclRefExprParts(DR, Parent));\r
-}\r
-void EnqueueVisitor::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {\r
- AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());\r
- AddDeclarationNameInfo(E);\r
- AddNestedNameSpecifierLoc(E->getQualifierLoc());\r
-}\r
-void EnqueueVisitor::VisitDeclStmt(DeclStmt *S) {\r
- unsigned size = WL.size();\r
- bool isFirst = true;\r
- for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();\r
- D != DEnd; ++D) {\r
- AddDecl(*D, isFirst);\r
- isFirst = false;\r
- }\r
- if (size == WL.size())\r
- return;\r
- // Now reverse the entries we just added. This will match the DFS\r
- // ordering performed by the worklist.\r
- VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();\r
- std::reverse(I, E);\r
-}\r
-void EnqueueVisitor::VisitDesignatedInitExpr(DesignatedInitExpr *E) {\r
- AddStmt(E->getInit());\r
- typedef DesignatedInitExpr::Designator Designator;\r
- for (DesignatedInitExpr::reverse_designators_iterator\r
- D = E->designators_rbegin(), DEnd = E->designators_rend();\r
- D != DEnd; ++D) {\r
- if (D->isFieldDesignator()) {\r
- if (FieldDecl *Field = D->getField())\r
- AddMemberRef(Field, D->getFieldLoc());\r
- continue;\r
- }\r
- if (D->isArrayDesignator()) {\r
- AddStmt(E->getArrayIndex(*D));\r
- continue;\r
- }\r
- assert(D->isArrayRangeDesignator() && "Unknown designator kind");\r
- AddStmt(E->getArrayRangeEnd(*D));\r
- AddStmt(E->getArrayRangeStart(*D));\r
- }\r
-}\r
-void EnqueueVisitor::VisitExplicitCastExpr(ExplicitCastExpr *E) {\r
- EnqueueChildren(E);\r
- AddTypeLoc(E->getTypeInfoAsWritten());\r
-}\r
-void EnqueueVisitor::VisitForStmt(ForStmt *FS) {\r
- AddStmt(FS->getBody());\r
- AddStmt(FS->getInc());\r
- AddStmt(FS->getCond());\r
- AddDecl(FS->getConditionVariable());\r
- AddStmt(FS->getInit());\r
-}\r
-void EnqueueVisitor::VisitGotoStmt(GotoStmt *GS) {\r
- WL.push_back(LabelRefVisit(GS->getLabel(), GS->getLabelLoc(), Parent));\r
-}\r
-void EnqueueVisitor::VisitIfStmt(IfStmt *If) {\r
- AddStmt(If->getElse());\r
- AddStmt(If->getThen());\r
- AddStmt(If->getCond());\r
- AddDecl(If->getConditionVariable());\r
-}\r
-void EnqueueVisitor::VisitInitListExpr(InitListExpr *IE) {\r
- // We care about the syntactic form of the initializer list, only.\r
- if (InitListExpr *Syntactic = IE->getSyntacticForm())\r
- IE = Syntactic;\r
- EnqueueChildren(IE);\r
-}\r
-void EnqueueVisitor::VisitMemberExpr(MemberExpr *M) {\r
- WL.push_back(MemberExprParts(M, Parent));\r
- \r
- // If the base of the member access expression is an implicit 'this', don't\r
- // visit it.\r
- // FIXME: If we ever want to show these implicit accesses, this will be\r
- // unfortunate. However, clang_getCursor() relies on this behavior.\r
- if (!M->isImplicitAccess())\r
- AddStmt(M->getBase());\r
-}\r
-void EnqueueVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {\r
- AddTypeLoc(E->getEncodedTypeSourceInfo());\r
-}\r
-void EnqueueVisitor::VisitObjCMessageExpr(ObjCMessageExpr *M) {\r
- EnqueueChildren(M);\r
- AddTypeLoc(M->getClassReceiverTypeInfo());\r
-}\r
-void EnqueueVisitor::VisitOffsetOfExpr(OffsetOfExpr *E) {\r
- // Visit the components of the offsetof expression.\r
- for (unsigned N = E->getNumComponents(), I = N; I > 0; --I) {\r
- typedef OffsetOfExpr::OffsetOfNode OffsetOfNode;\r
- const OffsetOfNode &Node = E->getComponent(I-1);\r
- switch (Node.getKind()) {\r
- case OffsetOfNode::Array:\r
- AddStmt(E->getIndexExpr(Node.getArrayExprIndex()));\r
- break;\r
- case OffsetOfNode::Field:\r
- AddMemberRef(Node.getField(), Node.getSourceRange().getEnd());\r
- break;\r
- case OffsetOfNode::Identifier:\r
- case OffsetOfNode::Base:\r
- continue;\r
- }\r
- }\r
- // Visit the type into which we're computing the offset.\r
- AddTypeLoc(E->getTypeSourceInfo());\r
-}\r
-void EnqueueVisitor::VisitOverloadExpr(OverloadExpr *E) {\r
- AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());\r
- WL.push_back(OverloadExprParts(E, Parent));\r
-}\r
-void EnqueueVisitor::VisitUnaryExprOrTypeTraitExpr(\r
- UnaryExprOrTypeTraitExpr *E) {\r
- EnqueueChildren(E);\r
- if (E->isArgumentType())\r
- AddTypeLoc(E->getArgumentTypeInfo());\r
-}\r
-void EnqueueVisitor::VisitStmt(Stmt *S) {\r
- EnqueueChildren(S);\r
-}\r
-void EnqueueVisitor::VisitSwitchStmt(SwitchStmt *S) {\r
- AddStmt(S->getBody());\r
- AddStmt(S->getCond());\r
- AddDecl(S->getConditionVariable());\r
-}\r
-\r
-void EnqueueVisitor::VisitWhileStmt(WhileStmt *W) {\r
- AddStmt(W->getBody());\r
- AddStmt(W->getCond());\r
- AddDecl(W->getConditionVariable());\r
-}\r
-\r
-void EnqueueVisitor::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {\r
- AddTypeLoc(E->getQueriedTypeSourceInfo());\r
-}\r
-\r
-void EnqueueVisitor::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {\r
- AddTypeLoc(E->getRhsTypeSourceInfo());\r
- AddTypeLoc(E->getLhsTypeSourceInfo());\r
-}\r
-\r
-void EnqueueVisitor::VisitTypeTraitExpr(TypeTraitExpr *E) {\r
- for (unsigned I = E->getNumArgs(); I > 0; --I)\r
- AddTypeLoc(E->getArg(I-1));\r
-}\r
-\r
-void EnqueueVisitor::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {\r
- AddTypeLoc(E->getQueriedTypeSourceInfo());\r
-}\r
-\r
-void EnqueueVisitor::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {\r
- EnqueueChildren(E);\r
-}\r
-\r
-void EnqueueVisitor::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U) {\r
- VisitOverloadExpr(U);\r
- if (!U->isImplicitAccess())\r
- AddStmt(U->getBase());\r
-}\r
-void EnqueueVisitor::VisitVAArgExpr(VAArgExpr *E) {\r
- AddStmt(E->getSubExpr());\r
- AddTypeLoc(E->getWrittenTypeInfo());\r
-}\r
-void EnqueueVisitor::VisitSizeOfPackExpr(SizeOfPackExpr *E) {\r
- WL.push_back(SizeOfPackExprParts(E, Parent));\r
-}\r
-void EnqueueVisitor::VisitOpaqueValueExpr(OpaqueValueExpr *E) {\r
- // If the opaque value has a source expression, just transparently\r
- // visit that. This is useful for (e.g.) pseudo-object expressions.\r
- if (Expr *SourceExpr = E->getSourceExpr())\r
- return Visit(SourceExpr);\r
-}\r
-void EnqueueVisitor::VisitLambdaExpr(LambdaExpr *E) {\r
- AddStmt(E->getBody());\r
- WL.push_back(LambdaExprParts(E, Parent));\r
-}\r
-void EnqueueVisitor::VisitPseudoObjectExpr(PseudoObjectExpr *E) {\r
- // Treat the expression like its syntactic form.\r
- Visit(E->getSyntacticForm());\r
-}\r
-\r
-void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, Stmt *S) {\r
- EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S);\r
-}\r
-\r
-bool CursorVisitor::IsInRegionOfInterest(CXCursor C) {\r
- if (RegionOfInterest.isValid()) {\r
- SourceRange Range = getRawCursorExtent(C);\r
- if (Range.isInvalid() || CompareRegionOfInterest(Range))\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {\r
- while (!WL.empty()) {\r
- // Dequeue the worklist item.\r
- VisitorJob LI = WL.back();\r
- WL.pop_back();\r
-\r
- // Set the Parent field, then back to its old value once we're done.\r
- SetParentRAII SetParent(Parent, StmtParent, LI.getParent());\r
- \r
- switch (LI.getKind()) {\r
- case VisitorJob::DeclVisitKind: {\r
- Decl *D = cast<DeclVisit>(&LI)->get();\r
- if (!D)\r
- continue;\r
-\r
- // For now, perform default visitation for Decls.\r
- if (Visit(MakeCXCursor(D, TU, RegionOfInterest,\r
- cast<DeclVisit>(&LI)->isFirst())))\r
- return true;\r
-\r
- continue;\r
- }\r
- case VisitorJob::ExplicitTemplateArgsVisitKind: {\r
- const ASTTemplateArgumentListInfo *ArgList =\r
- cast<ExplicitTemplateArgsVisit>(&LI)->get();\r
- for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(),\r
- *ArgEnd = Arg + ArgList->NumTemplateArgs;\r
- Arg != ArgEnd; ++Arg) {\r
- if (VisitTemplateArgumentLoc(*Arg))\r
- return true;\r
- }\r
- continue;\r
- }\r
- case VisitorJob::TypeLocVisitKind: {\r
- // Perform default visitation for TypeLocs.\r
- if (Visit(cast<TypeLocVisit>(&LI)->get()))\r
- return true;\r
- continue;\r
- }\r
- case VisitorJob::LabelRefVisitKind: {\r
- LabelDecl *LS = cast<LabelRefVisit>(&LI)->get();\r
- if (LabelStmt *stmt = LS->getStmt()) {\r
- if (Visit(MakeCursorLabelRef(stmt, cast<LabelRefVisit>(&LI)->getLoc(),\r
- TU))) {\r
- return true;\r
- }\r
- }\r
- continue;\r
- }\r
-\r
- case VisitorJob::NestedNameSpecifierLocVisitKind: {\r
- NestedNameSpecifierLocVisit *V = cast<NestedNameSpecifierLocVisit>(&LI);\r
- if (VisitNestedNameSpecifierLoc(V->get()))\r
- return true;\r
- continue;\r
- }\r
- \r
- case VisitorJob::DeclarationNameInfoVisitKind: {\r
- if (VisitDeclarationNameInfo(cast<DeclarationNameInfoVisit>(&LI)\r
- ->get()))\r
- return true;\r
- continue;\r
- }\r
- case VisitorJob::MemberRefVisitKind: {\r
- MemberRefVisit *V = cast<MemberRefVisit>(&LI);\r
- if (Visit(MakeCursorMemberRef(V->get(), V->getLoc(), TU)))\r
- return true;\r
- continue;\r
- }\r
- case VisitorJob::StmtVisitKind: {\r
- Stmt *S = cast<StmtVisit>(&LI)->get();\r
- if (!S)\r
- continue;\r
-\r
- // Update the current cursor.\r
- CXCursor Cursor = MakeCXCursor(S, StmtParent, TU, RegionOfInterest);\r
- if (!IsInRegionOfInterest(Cursor))\r
- continue;\r
- switch (Visitor(Cursor, Parent, ClientData)) {\r
- case CXChildVisit_Break: return true;\r
- case CXChildVisit_Continue: break;\r
- case CXChildVisit_Recurse:\r
- if (PostChildrenVisitor)\r
- WL.push_back(PostChildrenVisit(0, Cursor));\r
- EnqueueWorkList(WL, S);\r
- break;\r
- }\r
- continue;\r
- }\r
- case VisitorJob::MemberExprPartsKind: {\r
- // Handle the other pieces in the MemberExpr besides the base.\r
- MemberExpr *M = cast<MemberExprParts>(&LI)->get();\r
- \r
- // Visit the nested-name-specifier\r
- if (NestedNameSpecifierLoc QualifierLoc = M->getQualifierLoc())\r
- if (VisitNestedNameSpecifierLoc(QualifierLoc))\r
- return true;\r
- \r
- // Visit the declaration name.\r
- if (VisitDeclarationNameInfo(M->getMemberNameInfo()))\r
- return true;\r
- \r
- // Visit the explicitly-specified template arguments, if any.\r
- if (M->hasExplicitTemplateArgs()) {\r
- for (const TemplateArgumentLoc *Arg = M->getTemplateArgs(),\r
- *ArgEnd = Arg + M->getNumTemplateArgs();\r
- Arg != ArgEnd; ++Arg) {\r
- if (VisitTemplateArgumentLoc(*Arg))\r
- return true;\r
- }\r
- }\r
- continue;\r
- }\r
- case VisitorJob::DeclRefExprPartsKind: {\r
- DeclRefExpr *DR = cast<DeclRefExprParts>(&LI)->get();\r
- // Visit nested-name-specifier, if present.\r
- if (NestedNameSpecifierLoc QualifierLoc = DR->getQualifierLoc())\r
- if (VisitNestedNameSpecifierLoc(QualifierLoc))\r
- return true;\r
- // Visit declaration name.\r
- if (VisitDeclarationNameInfo(DR->getNameInfo()))\r
- return true;\r
- continue;\r
- }\r
- case VisitorJob::OverloadExprPartsKind: {\r
- OverloadExpr *O = cast<OverloadExprParts>(&LI)->get();\r
- // Visit the nested-name-specifier.\r
- if (NestedNameSpecifierLoc QualifierLoc = O->getQualifierLoc())\r
- if (VisitNestedNameSpecifierLoc(QualifierLoc))\r
- return true;\r
- // Visit the declaration name.\r
- if (VisitDeclarationNameInfo(O->getNameInfo()))\r
- return true;\r
- // Visit the overloaded declaration reference.\r
- if (Visit(MakeCursorOverloadedDeclRef(O, TU)))\r
- return true;\r
- continue;\r
- }\r
- case VisitorJob::SizeOfPackExprPartsKind: {\r
- SizeOfPackExpr *E = cast<SizeOfPackExprParts>(&LI)->get();\r
- NamedDecl *Pack = E->getPack();\r
- if (isa<TemplateTypeParmDecl>(Pack)) {\r
- if (Visit(MakeCursorTypeRef(cast<TemplateTypeParmDecl>(Pack),\r
- E->getPackLoc(), TU)))\r
- return true;\r
- \r
- continue;\r
- }\r
- \r
- if (isa<TemplateTemplateParmDecl>(Pack)) {\r
- if (Visit(MakeCursorTemplateRef(cast<TemplateTemplateParmDecl>(Pack),\r
- E->getPackLoc(), TU)))\r
- return true;\r
- \r
- continue;\r
- }\r
- \r
- // Non-type template parameter packs and function parameter packs are\r
- // treated like DeclRefExpr cursors.\r
- continue;\r
- }\r
- \r
- case VisitorJob::LambdaExprPartsKind: {\r
- // Visit captures.\r
- LambdaExpr *E = cast<LambdaExprParts>(&LI)->get();\r
- for (LambdaExpr::capture_iterator C = E->explicit_capture_begin(),\r
- CEnd = E->explicit_capture_end();\r
- C != CEnd; ++C) {\r
- if (C->capturesThis())\r
- continue;\r
- \r
- if (Visit(MakeCursorVariableRef(C->getCapturedVar(),\r
- C->getLocation(),\r
- TU)))\r
- return true;\r
- }\r
- \r
- // Visit parameters and return type, if present.\r
- if (E->hasExplicitParameters() || E->hasExplicitResultType()) {\r
- TypeLoc TL = E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();\r
- if (E->hasExplicitParameters() && E->hasExplicitResultType()) {\r
- // Visit the whole type.\r
- if (Visit(TL))\r
- return true;\r
- } else if (isa<FunctionProtoTypeLoc>(TL)) {\r
- FunctionProtoTypeLoc Proto = cast<FunctionProtoTypeLoc>(TL);\r
- if (E->hasExplicitParameters()) {\r
- // Visit parameters.\r
- for (unsigned I = 0, N = Proto.getNumArgs(); I != N; ++I)\r
- if (Visit(MakeCXCursor(Proto.getArg(I), TU)))\r
- return true;\r
- } else {\r
- // Visit result type.\r
- if (Visit(Proto.getResultLoc()))\r
- return true;\r
- }\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case VisitorJob::PostChildrenVisitKind:\r
- if (PostChildrenVisitor(Parent, ClientData))\r
- return true;\r
- break;\r
- }\r
- }\r
- return false;\r
-}\r
-\r
-bool CursorVisitor::Visit(Stmt *S) {\r
- VisitorWorkList *WL = 0;\r
- if (!WorkListFreeList.empty()) {\r
- WL = WorkListFreeList.back();\r
- WL->clear();\r
- WorkListFreeList.pop_back();\r
- }\r
- else {\r
- WL = new VisitorWorkList();\r
- WorkListCache.push_back(WL);\r
- }\r
- EnqueueWorkList(*WL, S);\r
- bool result = RunVisitorWorkList(*WL);\r
- WorkListFreeList.push_back(WL);\r
- return result;\r
-}\r
-\r
-namespace {\r
-typedef llvm::SmallVector<SourceRange, 4> RefNamePieces;\r
-RefNamePieces buildPieces(unsigned NameFlags, bool IsMemberRefExpr, \r
- const DeclarationNameInfo &NI, \r
- const SourceRange &QLoc, \r
- const ASTTemplateArgumentListInfo *TemplateArgs = 0){\r
- const bool WantQualifier = NameFlags & CXNameRange_WantQualifier;\r
- const bool WantTemplateArgs = NameFlags & CXNameRange_WantTemplateArgs;\r
- const bool WantSinglePiece = NameFlags & CXNameRange_WantSinglePiece;\r
- \r
- const DeclarationName::NameKind Kind = NI.getName().getNameKind();\r
- \r
- RefNamePieces Pieces;\r
-\r
- if (WantQualifier && QLoc.isValid())\r
- Pieces.push_back(QLoc);\r
- \r
- if (Kind != DeclarationName::CXXOperatorName || IsMemberRefExpr)\r
- Pieces.push_back(NI.getLoc());\r
- \r
- if (WantTemplateArgs && TemplateArgs)\r
- Pieces.push_back(SourceRange(TemplateArgs->LAngleLoc,\r
- TemplateArgs->RAngleLoc));\r
- \r
- if (Kind == DeclarationName::CXXOperatorName) {\r
- Pieces.push_back(SourceLocation::getFromRawEncoding(\r
- NI.getInfo().CXXOperatorName.BeginOpNameLoc));\r
- Pieces.push_back(SourceLocation::getFromRawEncoding(\r
- NI.getInfo().CXXOperatorName.EndOpNameLoc));\r
- }\r
- \r
- if (WantSinglePiece) {\r
- SourceRange R(Pieces.front().getBegin(), Pieces.back().getEnd());\r
- Pieces.clear();\r
- Pieces.push_back(R);\r
- } \r
-\r
- return Pieces; \r
-}\r
-}\r
-\r
-//===----------------------------------------------------------------------===//\r
-// Misc. API hooks.\r
-//===----------------------------------------------------------------------===// \r
-\r
-static llvm::sys::Mutex EnableMultithreadingMutex;\r
-static bool EnabledMultithreading;\r
-\r
-static void fatal_error_handler(void *user_data, const std::string& reason) {\r
- // Write the result out to stderr avoiding errs() because raw_ostreams can\r
- // call report_fatal_error.\r
- fprintf(stderr, "LIBCLANG FATAL ERROR: %s\n", reason.c_str());\r
- ::abort();\r
-}\r
-\r
-extern "C" {\r
-CXIndex clang_createIndex(int excludeDeclarationsFromPCH,\r
- int displayDiagnostics) {\r
- // Disable pretty stack trace functionality, which will otherwise be a very\r
- // poor citizen of the world and set up all sorts of signal handlers.\r
- llvm::DisablePrettyStackTrace = true;\r
-\r
- // We use crash recovery to make some of our APIs more reliable, implicitly\r
- // enable it.\r
- llvm::CrashRecoveryContext::Enable();\r
-\r
- // Enable support for multithreading in LLVM.\r
- {\r
- llvm::sys::ScopedLock L(EnableMultithreadingMutex);\r
- if (!EnabledMultithreading) {\r
- llvm::install_fatal_error_handler(fatal_error_handler, 0);\r
- llvm::llvm_start_multithreaded();\r
- EnabledMultithreading = true;\r
- }\r
- }\r
-\r
- CIndexer *CIdxr = new CIndexer();\r
- if (excludeDeclarationsFromPCH)\r
- CIdxr->setOnlyLocalDecls();\r
- if (displayDiagnostics)\r
- CIdxr->setDisplayDiagnostics();\r
-\r
- if (getenv("LIBCLANG_BGPRIO_INDEX"))\r
- CIdxr->setCXGlobalOptFlags(CIdxr->getCXGlobalOptFlags() |\r
- CXGlobalOpt_ThreadBackgroundPriorityForIndexing);\r
- if (getenv("LIBCLANG_BGPRIO_EDIT"))\r
- CIdxr->setCXGlobalOptFlags(CIdxr->getCXGlobalOptFlags() |\r
- CXGlobalOpt_ThreadBackgroundPriorityForEditing);\r
-\r
- return CIdxr;\r
-}\r
-\r
-void clang_disposeIndex(CXIndex CIdx) {\r
- if (CIdx)\r
- delete static_cast<CIndexer *>(CIdx);\r
-}\r
-\r
-void clang_CXIndex_setGlobalOptions(CXIndex CIdx, unsigned options) {\r
- if (CIdx)\r
- static_cast<CIndexer *>(CIdx)->setCXGlobalOptFlags(options);\r
-}\r
-\r
-unsigned clang_CXIndex_getGlobalOptions(CXIndex CIdx) {\r
- if (CIdx)\r
- return static_cast<CIndexer *>(CIdx)->getCXGlobalOptFlags();\r
- return 0;\r
-}\r
-\r
-void clang_toggleCrashRecovery(unsigned isEnabled) {\r
- if (isEnabled)\r
- llvm::CrashRecoveryContext::Enable();\r
- else\r
- llvm::CrashRecoveryContext::Disable();\r
-}\r
- \r
-CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,\r
- const char *ast_filename) {\r
- if (!CIdx)\r
- return 0;\r
-\r
- CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);\r
- FileSystemOptions FileSystemOpts;\r
-\r
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags;\r
- ASTUnit *TU = ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts,\r
- CXXIdx->getOnlyLocalDecls(),\r
- 0, 0,\r
- /*CaptureDiagnostics=*/true,\r
- /*AllowPCHWithCompilerErrors=*/true,\r
- /*UserFilesAreVolatile=*/true);\r
- return MakeCXTranslationUnit(CXXIdx, TU);\r
-}\r
-\r
-unsigned clang_defaultEditingTranslationUnitOptions() {\r
- return CXTranslationUnit_PrecompiledPreamble | \r
- CXTranslationUnit_CacheCompletionResults;\r
-}\r
- \r
-CXTranslationUnit\r
-clang_createTranslationUnitFromSourceFile(CXIndex CIdx,\r
- const char *source_filename,\r
- int num_command_line_args,\r
- const char * const *command_line_args,\r
- unsigned num_unsaved_files,\r
- struct CXUnsavedFile *unsaved_files) {\r
- unsigned Options = CXTranslationUnit_DetailedPreprocessingRecord;\r
- return clang_parseTranslationUnit(CIdx, source_filename,\r
- command_line_args, num_command_line_args,\r
- unsaved_files, num_unsaved_files,\r
- Options);\r
-}\r
-\r
-struct ParseTranslationUnitInfo {\r
- CXIndex CIdx;\r
- const char *source_filename;\r
- const char *const *command_line_args;\r
- int num_command_line_args;\r
- struct CXUnsavedFile *unsaved_files;\r
- unsigned num_unsaved_files;\r
- unsigned options;\r
- CXTranslationUnit result;\r
-};\r
-static void clang_parseTranslationUnit_Impl(void *UserData) {\r
- ParseTranslationUnitInfo *PTUI =\r
- static_cast<ParseTranslationUnitInfo*>(UserData);\r
- CXIndex CIdx = PTUI->CIdx;\r
- const char *source_filename = PTUI->source_filename;\r
- const char * const *command_line_args = PTUI->command_line_args;\r
- int num_command_line_args = PTUI->num_command_line_args;\r
- struct CXUnsavedFile *unsaved_files = PTUI->unsaved_files;\r
- unsigned num_unsaved_files = PTUI->num_unsaved_files;\r
- unsigned options = PTUI->options;\r
- PTUI->result = 0;\r
-\r
- if (!CIdx)\r
- return;\r
-\r
- CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);\r
-\r
- if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))\r
- setThreadBackgroundPriority();\r
-\r
- bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble;\r
- // FIXME: Add a flag for modules.\r
- TranslationUnitKind TUKind\r
- = (options & CXTranslationUnit_Incomplete)? TU_Prefix : TU_Complete;\r
- bool CacheCodeCompetionResults\r
- = options & CXTranslationUnit_CacheCompletionResults;\r
- bool IncludeBriefCommentsInCodeCompletion\r
- = options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;\r
- bool SkipFunctionBodies = options & CXTranslationUnit_SkipFunctionBodies;\r
- bool ForSerialization = options & CXTranslationUnit_ForSerialization;\r
-\r
- // Configure the diagnostics.\r
- IntrusiveRefCntPtr<DiagnosticsEngine>\r
- Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions,\r
- num_command_line_args,\r
- command_line_args));\r
-\r
- // Recover resources if we crash before exiting this function.\r
- llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,\r
- llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >\r
- DiagCleanup(Diags.getPtr());\r
-\r
- OwningPtr<std::vector<ASTUnit::RemappedFile> >\r
- RemappedFiles(new std::vector<ASTUnit::RemappedFile>());\r
-\r
- // Recover resources if we crash before exiting this function.\r
- llvm::CrashRecoveryContextCleanupRegistrar<\r
- std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());\r
-\r
- for (unsigned I = 0; I != num_unsaved_files; ++I) {\r
- StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);\r
- const llvm::MemoryBuffer *Buffer\r
- = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);\r
- RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename,\r
- Buffer));\r
- }\r
-\r
- OwningPtr<std::vector<const char *> >\r
- Args(new std::vector<const char*>());\r
-\r
- // Recover resources if we crash before exiting this method.\r
- llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> >\r
- ArgsCleanup(Args.get());\r
-\r
- // Since the Clang C library is primarily used by batch tools dealing with\r
- // (often very broken) source code, where spell-checking can have a\r
- // significant negative impact on performance (particularly when \r
- // precompiled headers are involved), we disable it by default.\r
- // Only do this if we haven't found a spell-checking-related argument.\r
- bool FoundSpellCheckingArgument = false;\r
- for (int I = 0; I != num_command_line_args; ++I) {\r
- if (strcmp(command_line_args[I], "-fno-spell-checking") == 0 ||\r
- strcmp(command_line_args[I], "-fspell-checking") == 0) {\r
- FoundSpellCheckingArgument = true;\r
- break;\r
- }\r
- }\r
- if (!FoundSpellCheckingArgument)\r
- Args->push_back("-fno-spell-checking");\r
- \r
- Args->insert(Args->end(), command_line_args,\r
- command_line_args + num_command_line_args);\r
-\r
- // The 'source_filename' argument is optional. If the caller does not\r
- // specify it then it is assumed that the source file is specified\r
- // in the actual argument list.\r
- // Put the source file after command_line_args otherwise if '-x' flag is\r
- // present it will be unused.\r
- if (source_filename)\r
- Args->push_back(source_filename);\r
-\r
- // Do we need the detailed preprocessing record?\r
- if (options & CXTranslationUnit_DetailedPreprocessingRecord) {\r
- Args->push_back("-Xclang");\r
- Args->push_back("-detailed-preprocessing-record");\r
- }\r
- \r
- unsigned NumErrors = Diags->getClient()->getNumErrors();\r
- OwningPtr<ASTUnit> ErrUnit;\r
- OwningPtr<ASTUnit> Unit(\r
- ASTUnit::LoadFromCommandLine(Args->size() ? &(*Args)[0] : 0 \r
- /* vector::data() not portable */,\r
- Args->size() ? (&(*Args)[0] + Args->size()) :0,\r
- Diags,\r
- CXXIdx->getClangResourcesPath(),\r
- CXXIdx->getOnlyLocalDecls(),\r
- /*CaptureDiagnostics=*/true,\r
- RemappedFiles->size() ? &(*RemappedFiles)[0]:0,\r
- RemappedFiles->size(),\r
- /*RemappedFilesKeepOriginalName=*/true,\r
- PrecompilePreamble,\r
- TUKind,\r
- CacheCodeCompetionResults,\r
- IncludeBriefCommentsInCodeCompletion,\r
- /*AllowPCHWithCompilerErrors=*/true,\r
- SkipFunctionBodies,\r
- /*UserFilesAreVolatile=*/true,\r
- ForSerialization,\r
- &ErrUnit));\r
-\r
- if (NumErrors != Diags->getClient()->getNumErrors()) {\r
- // Make sure to check that 'Unit' is non-NULL.\r
- if (CXXIdx->getDisplayDiagnostics())\r
- printDiagsToStderr(Unit ? Unit.get() : ErrUnit.get());\r
- }\r
-\r
- PTUI->result = MakeCXTranslationUnit(CXXIdx, Unit.take());\r
-}\r
-CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,\r
- const char *source_filename,\r
- const char * const *command_line_args,\r
- int num_command_line_args,\r
- struct CXUnsavedFile *unsaved_files,\r
- unsigned num_unsaved_files,\r
- unsigned options) {\r
- ParseTranslationUnitInfo PTUI = { CIdx, source_filename, command_line_args,\r
- num_command_line_args, unsaved_files,\r
- num_unsaved_files, options, 0 };\r
- llvm::CrashRecoveryContext CRC;\r
-\r
- if (!RunSafely(CRC, clang_parseTranslationUnit_Impl, &PTUI)) {\r
- fprintf(stderr, "libclang: crash detected during parsing: {\n");\r
- fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);\r
- fprintf(stderr, " 'command_line_args' : [");\r
- for (int i = 0; i != num_command_line_args; ++i) {\r
- if (i)\r
- fprintf(stderr, ", ");\r
- fprintf(stderr, "'%s'", command_line_args[i]);\r
- }\r
- fprintf(stderr, "],\n");\r
- fprintf(stderr, " 'unsaved_files' : [");\r
- for (unsigned i = 0; i != num_unsaved_files; ++i) {\r
- if (i)\r
- fprintf(stderr, ", ");\r
- fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,\r
- unsaved_files[i].Length);\r
- }\r
- fprintf(stderr, "],\n");\r
- fprintf(stderr, " 'options' : %d,\n", options);\r
- fprintf(stderr, "}\n");\r
- \r
- return 0;\r
- } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {\r
- PrintLibclangResourceUsage(PTUI.result);\r
- }\r
- \r
- return PTUI.result;\r
-}\r
-\r
-unsigned clang_defaultSaveOptions(CXTranslationUnit TU) {\r
- return CXSaveTranslationUnit_None;\r
-} \r
-\r
-namespace {\r
-\r
-struct SaveTranslationUnitInfo {\r
- CXTranslationUnit TU;\r
- const char *FileName;\r
- unsigned options;\r
- CXSaveError result;\r
-};\r
-\r
-}\r
-\r
-static void clang_saveTranslationUnit_Impl(void *UserData) {\r
- SaveTranslationUnitInfo *STUI =\r
- static_cast<SaveTranslationUnitInfo*>(UserData);\r
-\r
- CIndexer *CXXIdx = (CIndexer*)STUI->TU->CIdx;\r
- if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))\r
- setThreadBackgroundPriority();\r
-\r
- bool hadError = static_cast<ASTUnit *>(STUI->TU->TUData)->Save(STUI->FileName);\r
- STUI->result = hadError ? CXSaveError_Unknown : CXSaveError_None;\r
-}\r
-\r
-int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,\r
- unsigned options) {\r
- if (!TU)\r
- return CXSaveError_InvalidTU;\r
-\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);\r
- ASTUnit::ConcurrencyCheck Check(*CXXUnit);\r
- if (!CXXUnit->hasSema())\r
- return CXSaveError_InvalidTU;\r
-\r
- SaveTranslationUnitInfo STUI = { TU, FileName, options, CXSaveError_None };\r
-\r
- if (!CXXUnit->getDiagnostics().hasUnrecoverableErrorOccurred() ||\r
- getenv("LIBCLANG_NOTHREADS")) {\r
- clang_saveTranslationUnit_Impl(&STUI);\r
-\r
- if (getenv("LIBCLANG_RESOURCE_USAGE"))\r
- PrintLibclangResourceUsage(TU);\r
-\r
- return STUI.result;\r
- }\r
-\r
- // We have an AST that has invalid nodes due to compiler errors.\r
- // Use a crash recovery thread for protection.\r
-\r
- llvm::CrashRecoveryContext CRC;\r
-\r
- if (!RunSafely(CRC, clang_saveTranslationUnit_Impl, &STUI)) {\r
- fprintf(stderr, "libclang: crash detected during AST saving: {\n");\r
- fprintf(stderr, " 'filename' : '%s'\n", FileName);\r
- fprintf(stderr, " 'options' : %d,\n", options);\r
- fprintf(stderr, "}\n");\r
-\r
- return CXSaveError_Unknown;\r
-\r
- } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {\r
- PrintLibclangResourceUsage(TU);\r
- }\r
-\r
- return STUI.result;\r
-}\r
-\r
-void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {\r
- if (CTUnit) {\r
- // If the translation unit has been marked as unsafe to free, just discard\r
- // it.\r
- if (static_cast<ASTUnit *>(CTUnit->TUData)->isUnsafeToFree())\r
- return;\r
-\r
- delete static_cast<ASTUnit *>(CTUnit->TUData);\r
- disposeCXStringPool(CTUnit->StringPool);\r
- delete static_cast<CXDiagnosticSetImpl *>(CTUnit->Diagnostics);\r
- disposeOverridenCXCursorsPool(CTUnit->OverridenCursorsPool);\r
- delete CTUnit;\r
- }\r
-}\r
-\r
-unsigned clang_defaultReparseOptions(CXTranslationUnit TU) {\r
- return CXReparse_None;\r
-}\r
-\r
-struct ReparseTranslationUnitInfo {\r
- CXTranslationUnit TU;\r
- unsigned num_unsaved_files;\r
- struct CXUnsavedFile *unsaved_files;\r
- unsigned options;\r
- int result;\r
-};\r
-\r
-static void clang_reparseTranslationUnit_Impl(void *UserData) {\r
- ReparseTranslationUnitInfo *RTUI =\r
- static_cast<ReparseTranslationUnitInfo*>(UserData);\r
- CXTranslationUnit TU = RTUI->TU;\r
-\r
- // Reset the associated diagnostics.\r
- delete static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);\r
- TU->Diagnostics = 0;\r
-\r
- unsigned num_unsaved_files = RTUI->num_unsaved_files;\r
- struct CXUnsavedFile *unsaved_files = RTUI->unsaved_files;\r
- unsigned options = RTUI->options;\r
- (void) options;\r
- RTUI->result = 1;\r
-\r
- if (!TU)\r
- return;\r
-\r
- CIndexer *CXXIdx = (CIndexer*)TU->CIdx;\r
- if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))\r
- setThreadBackgroundPriority();\r
-\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);\r
- ASTUnit::ConcurrencyCheck Check(*CXXUnit);\r
- \r
- OwningPtr<std::vector<ASTUnit::RemappedFile> >\r
- RemappedFiles(new std::vector<ASTUnit::RemappedFile>());\r
- \r
- // Recover resources if we crash before exiting this function.\r
- llvm::CrashRecoveryContextCleanupRegistrar<\r
- std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());\r
- \r
- for (unsigned I = 0; I != num_unsaved_files; ++I) {\r
- StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);\r
- const llvm::MemoryBuffer *Buffer\r
- = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);\r
- RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename,\r
- Buffer));\r
- }\r
- \r
- if (!CXXUnit->Reparse(RemappedFiles->size() ? &(*RemappedFiles)[0] : 0,\r
- RemappedFiles->size()))\r
- RTUI->result = 0;\r
-}\r
-\r
-int clang_reparseTranslationUnit(CXTranslationUnit TU,\r
- unsigned num_unsaved_files,\r
- struct CXUnsavedFile *unsaved_files,\r
- unsigned options) {\r
- ReparseTranslationUnitInfo RTUI = { TU, num_unsaved_files, unsaved_files,\r
- options, 0 };\r
-\r
- if (getenv("LIBCLANG_NOTHREADS")) {\r
- clang_reparseTranslationUnit_Impl(&RTUI);\r
- return RTUI.result;\r
- }\r
-\r
- llvm::CrashRecoveryContext CRC;\r
-\r
- if (!RunSafely(CRC, clang_reparseTranslationUnit_Impl, &RTUI)) {\r
- fprintf(stderr, "libclang: crash detected during reparsing\n");\r
- static_cast<ASTUnit *>(TU->TUData)->setUnsafeToFree(true);\r
- return 1;\r
- } else if (getenv("LIBCLANG_RESOURCE_USAGE"))\r
- PrintLibclangResourceUsage(TU);\r
-\r
- return RTUI.result;\r
-}\r
-\r
-\r
-CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {\r
- if (!CTUnit)\r
- return createCXString("");\r
-\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit->TUData);\r
- return createCXString(CXXUnit->getOriginalSourceFileName(), true);\r
-}\r
-\r
-CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {\r
- ASTUnit *CXXUnit = static_cast<ASTUnit*>(TU->TUData);\r
- return MakeCXCursor(CXXUnit->getASTContext().getTranslationUnitDecl(), TU);\r
-}\r
-\r
-} // end: extern "C"\r
-\r
-//===----------------------------------------------------------------------===//\r
-// CXFile Operations.\r
-//===----------------------------------------------------------------------===//\r
-\r
-extern "C" {\r
-CXString clang_getFileName(CXFile SFile) {\r
- if (!SFile)\r
- return createCXString((const char*)NULL);\r
-\r
- FileEntry *FEnt = static_cast<FileEntry *>(SFile);\r
- return createCXString(FEnt->getName());\r
-}\r
-\r
-time_t clang_getFileTime(CXFile SFile) {\r
- if (!SFile)\r
- return 0;\r
-\r
- FileEntry *FEnt = static_cast<FileEntry *>(SFile);\r
- return FEnt->getModificationTime();\r
-}\r
-\r
-CXFile clang_getFile(CXTranslationUnit tu, const char *file_name) {\r
- if (!tu)\r
- return 0;\r
-\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);\r
-\r
- FileManager &FMgr = CXXUnit->getFileManager();\r
- return const_cast<FileEntry *>(FMgr.getFile(file_name));\r
-}\r
-\r
-unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file) {\r
- if (!tu || !file)\r
- return 0;\r
-\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);\r
- FileEntry *FEnt = static_cast<FileEntry *>(file);\r
- return CXXUnit->getPreprocessor().getHeaderSearchInfo()\r
- .isFileMultipleIncludeGuarded(FEnt);\r
-}\r
-\r
-} // end: extern "C"\r
-\r
-//===----------------------------------------------------------------------===//\r
-// CXCursor Operations.\r
-//===----------------------------------------------------------------------===//\r
-\r
-static Decl *getDeclFromExpr(Stmt *E) {\r
- if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))\r
- return getDeclFromExpr(CE->getSubExpr());\r
-\r
- if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))\r
- return RefExpr->getDecl();\r
- if (MemberExpr *ME = dyn_cast<MemberExpr>(E))\r
- return ME->getMemberDecl();\r
- if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))\r
- return RE->getDecl();\r
- if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(E)) {\r
- if (PRE->isExplicitProperty())\r
- return PRE->getExplicitProperty();\r
- // It could be messaging both getter and setter as in:\r
- // ++myobj.myprop;\r
- // in which case prefer to associate the setter since it is less obvious\r
- // from inspecting the source that the setter is going to get called.\r
- if (PRE->isMessagingSetter())\r
- return PRE->getImplicitPropertySetter();\r
- return PRE->getImplicitPropertyGetter();\r
- }\r
- if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))\r
- return getDeclFromExpr(POE->getSyntacticForm());\r
- if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))\r
- if (Expr *Src = OVE->getSourceExpr())\r
- return getDeclFromExpr(Src);\r
- \r
- if (CallExpr *CE = dyn_cast<CallExpr>(E))\r
- return getDeclFromExpr(CE->getCallee());\r
- if (CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E))\r
- if (!CE->isElidable())\r
- return CE->getConstructor();\r
- if (ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(E))\r
- return OME->getMethodDecl();\r
-\r
- if (ObjCProtocolExpr *PE = dyn_cast<ObjCProtocolExpr>(E))\r
- return PE->getProtocol();\r
- if (SubstNonTypeTemplateParmPackExpr *NTTP \r
- = dyn_cast<SubstNonTypeTemplateParmPackExpr>(E))\r
- return NTTP->getParameterPack();\r
- if (SizeOfPackExpr *SizeOfPack = dyn_cast<SizeOfPackExpr>(E))\r
- if (isa<NonTypeTemplateParmDecl>(SizeOfPack->getPack()) || \r
- isa<ParmVarDecl>(SizeOfPack->getPack()))\r
- return SizeOfPack->getPack();\r
- \r
- return 0;\r
-}\r
-\r
-static SourceLocation getLocationFromExpr(Expr *E) {\r
- if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))\r
- return getLocationFromExpr(CE->getSubExpr());\r
-\r
- if (ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E))\r
- return /*FIXME:*/Msg->getLeftLoc();\r
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))\r
- return DRE->getLocation();\r
- if (MemberExpr *Member = dyn_cast<MemberExpr>(E))\r
- return Member->getMemberLoc();\r
- if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E))\r
- return Ivar->getLocation();\r
- if (SizeOfPackExpr *SizeOfPack = dyn_cast<SizeOfPackExpr>(E))\r
- return SizeOfPack->getPackLoc();\r
- if (ObjCPropertyRefExpr *PropRef = dyn_cast<ObjCPropertyRefExpr>(E))\r
- return PropRef->getLocation();\r
- \r
- return E->getLocStart();\r
-}\r
-\r
-extern "C" {\r
-\r
-unsigned clang_visitChildren(CXCursor parent,\r
- CXCursorVisitor visitor,\r
- CXClientData client_data) {\r
- CursorVisitor CursorVis(getCursorTU(parent), visitor, client_data,\r
- /*VisitPreprocessorLast=*/false);\r
- return CursorVis.VisitChildren(parent);\r
-}\r
-\r
-#ifndef __has_feature\r
-#define __has_feature(x) 0\r
-#endif\r
-#if __has_feature(blocks)\r
-typedef enum CXChildVisitResult \r
- (^CXCursorVisitorBlock)(CXCursor cursor, CXCursor parent);\r
-\r
-static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,\r
- CXClientData client_data) {\r
- CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data;\r
- return block(cursor, parent);\r
-}\r
-#else\r
-// If we are compiled with a compiler that doesn't have native blocks support,\r
-// define and call the block manually, so the \r
-typedef struct _CXChildVisitResult\r
-{\r
- void *isa;\r
- int flags;\r
- int reserved;\r
- enum CXChildVisitResult(*invoke)(struct _CXChildVisitResult*, CXCursor,\r
- CXCursor);\r
-} *CXCursorVisitorBlock;\r
-\r
-static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,\r
- CXClientData client_data) {\r
- CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data;\r
- return block->invoke(block, cursor, parent);\r
-}\r
-#endif\r
-\r
-\r
-unsigned clang_visitChildrenWithBlock(CXCursor parent,\r
- CXCursorVisitorBlock block) {\r
- return clang_visitChildren(parent, visitWithBlock, block);\r
-}\r
-\r
-static CXString getDeclSpelling(Decl *D) {\r
- if (!D)\r
- return createCXString("");\r
-\r
- NamedDecl *ND = dyn_cast<NamedDecl>(D);\r
- if (!ND) {\r
- if (ObjCPropertyImplDecl *PropImpl =dyn_cast<ObjCPropertyImplDecl>(D))\r
- if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())\r
- return createCXString(Property->getIdentifier()->getName());\r
- \r
- if (ImportDecl *ImportD = dyn_cast<ImportDecl>(D))\r
- if (Module *Mod = ImportD->getImportedModule())\r
- return createCXString(Mod->getFullModuleName());\r
-\r
- return createCXString("");\r
- }\r
- \r
- if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))\r
- return createCXString(OMD->getSelector().getAsString());\r
-\r
- if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))\r
- // No, this isn't the same as the code below. getIdentifier() is non-virtual\r
- // and returns different names. NamedDecl returns the class name and\r
- // ObjCCategoryImplDecl returns the category name.\r
- return createCXString(CIMP->getIdentifier()->getNameStart());\r
-\r
- if (isa<UsingDirectiveDecl>(D))\r
- return createCXString("");\r
- \r
- SmallString<1024> S;\r
- llvm::raw_svector_ostream os(S);\r
- ND->printName(os);\r
- \r
- return createCXString(os.str());\r
-}\r
-\r
-CXString clang_getCursorSpelling(CXCursor C) {\r
- if (clang_isTranslationUnit(C.kind))\r
- return clang_getTranslationUnitSpelling(\r
- static_cast<CXTranslationUnit>(C.data[2]));\r
-\r
- if (clang_isReference(C.kind)) {\r
- switch (C.kind) {\r
- case CXCursor_ObjCSuperClassRef: {\r
- ObjCInterfaceDecl *Super = getCursorObjCSuperClassRef(C).first;\r
- return createCXString(Super->getIdentifier()->getNameStart());\r
- }\r
- case CXCursor_ObjCClassRef: {\r
- ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;\r
- return createCXString(Class->getIdentifier()->getNameStart());\r
- }\r
- case CXCursor_ObjCProtocolRef: {\r
- ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first;\r
- assert(OID && "getCursorSpelling(): Missing protocol decl");\r
- return createCXString(OID->getIdentifier()->getNameStart());\r
- }\r
- case CXCursor_CXXBaseSpecifier: {\r
- CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);\r
- return createCXString(B->getType().getAsString());\r
- }\r
- case CXCursor_TypeRef: {\r
- TypeDecl *Type = getCursorTypeRef(C).first;\r
- assert(Type && "Missing type decl");\r
-\r
- return createCXString(getCursorContext(C).getTypeDeclType(Type).\r
- getAsString());\r
- }\r
- case CXCursor_TemplateRef: {\r
- TemplateDecl *Template = getCursorTemplateRef(C).first;\r
- assert(Template && "Missing template decl");\r
- \r
- return createCXString(Template->getNameAsString());\r
- }\r
- \r
- case CXCursor_NamespaceRef: {\r
- NamedDecl *NS = getCursorNamespaceRef(C).first;\r
- assert(NS && "Missing namespace decl");\r
- \r
- return createCXString(NS->getNameAsString());\r
- }\r
-\r
- case CXCursor_MemberRef: {\r
- FieldDecl *Field = getCursorMemberRef(C).first;\r
- assert(Field && "Missing member decl");\r
- \r
- return createCXString(Field->getNameAsString());\r
- }\r
-\r
- case CXCursor_LabelRef: {\r
- LabelStmt *Label = getCursorLabelRef(C).first;\r
- assert(Label && "Missing label");\r
- \r
- return createCXString(Label->getName());\r
- }\r
-\r
- case CXCursor_OverloadedDeclRef: {\r
- OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;\r
- if (Decl *D = Storage.dyn_cast<Decl *>()) {\r
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D))\r
- return createCXString(ND->getNameAsString());\r
- return createCXString("");\r
- }\r
- if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>())\r
- return createCXString(E->getName().getAsString());\r
- OverloadedTemplateStorage *Ovl\r
- = Storage.get<OverloadedTemplateStorage*>();\r
- if (Ovl->size() == 0)\r
- return createCXString("");\r
- return createCXString((*Ovl->begin())->getNameAsString());\r
- }\r
- \r
- case CXCursor_VariableRef: {\r
- VarDecl *Var = getCursorVariableRef(C).first;\r
- assert(Var && "Missing variable decl");\r
- \r
- return createCXString(Var->getNameAsString());\r
- }\r
- \r
- default:\r
- return createCXString("<not implemented>");\r
- }\r
- }\r
-\r
- if (clang_isExpression(C.kind)) {\r
- Decl *D = getDeclFromExpr(getCursorExpr(C));\r
- if (D)\r
- return getDeclSpelling(D);\r
- return createCXString("");\r
- }\r
-\r
- if (clang_isStatement(C.kind)) {\r
- Stmt *S = getCursorStmt(C);\r
- if (LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))\r
- return createCXString(Label->getName());\r
-\r
- return createCXString("");\r
- }\r
- \r
- if (C.kind == CXCursor_MacroExpansion)\r
- return createCXString(getCursorMacroExpansion(C)->getName()\r
- ->getNameStart());\r
-\r
- if (C.kind == CXCursor_MacroDefinition)\r
- return createCXString(getCursorMacroDefinition(C)->getName()\r
- ->getNameStart());\r
-\r
- if (C.kind == CXCursor_InclusionDirective)\r
- return createCXString(getCursorInclusionDirective(C)->getFileName());\r
- \r
- if (clang_isDeclaration(C.kind))\r
- return getDeclSpelling(getCursorDecl(C));\r
-\r
- if (C.kind == CXCursor_AnnotateAttr) {\r
- AnnotateAttr *AA = cast<AnnotateAttr>(cxcursor::getCursorAttr(C));\r
- return createCXString(AA->getAnnotation());\r
- }\r
-\r
- if (C.kind == CXCursor_AsmLabelAttr) {\r
- AsmLabelAttr *AA = cast<AsmLabelAttr>(cxcursor::getCursorAttr(C));\r
- return createCXString(AA->getLabel());\r
- }\r
-\r
- return createCXString("");\r
-}\r
-\r
-CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor C,\r
- unsigned pieceIndex,\r
- unsigned options) {\r
- if (clang_Cursor_isNull(C))\r
- return clang_getNullRange();\r
-\r
- ASTContext &Ctx = getCursorContext(C);\r
-\r
- if (clang_isStatement(C.kind)) {\r
- Stmt *S = getCursorStmt(C);\r
- if (LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S)) {\r
- if (pieceIndex > 0)\r
- return clang_getNullRange();\r
- return cxloc::translateSourceRange(Ctx, Label->getIdentLoc());\r
- }\r
-\r
- return clang_getNullRange();\r
- }\r
-\r
- if (C.kind == CXCursor_ObjCMessageExpr) {\r
- if (ObjCMessageExpr *\r
- ME = dyn_cast_or_null<ObjCMessageExpr>(getCursorExpr(C))) {\r
- if (pieceIndex >= ME->getNumSelectorLocs())\r
- return clang_getNullRange();\r
- return cxloc::translateSourceRange(Ctx, ME->getSelectorLoc(pieceIndex));\r
- }\r
- }\r
-\r
- if (C.kind == CXCursor_ObjCInstanceMethodDecl ||\r
- C.kind == CXCursor_ObjCClassMethodDecl) {\r
- if (ObjCMethodDecl *\r
- MD = dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(C))) {\r
- if (pieceIndex >= MD->getNumSelectorLocs())\r
- return clang_getNullRange();\r
- return cxloc::translateSourceRange(Ctx, MD->getSelectorLoc(pieceIndex));\r
- }\r
- }\r
-\r
- if (C.kind == CXCursor_ObjCCategoryDecl ||\r
- C.kind == CXCursor_ObjCCategoryImplDecl) {\r
- if (pieceIndex > 0)\r
- return clang_getNullRange();\r
- if (ObjCCategoryDecl *\r
- CD = dyn_cast_or_null<ObjCCategoryDecl>(getCursorDecl(C)))\r
- return cxloc::translateSourceRange(Ctx, CD->getCategoryNameLoc());\r
- if (ObjCCategoryImplDecl *\r
- CID = dyn_cast_or_null<ObjCCategoryImplDecl>(getCursorDecl(C)))\r
- return cxloc::translateSourceRange(Ctx, CID->getCategoryNameLoc());\r
- }\r
-\r
- if (C.kind == CXCursor_ModuleImportDecl) {\r
- if (pieceIndex > 0)\r
- return clang_getNullRange();\r
- if (ImportDecl *ImportD = dyn_cast_or_null<ImportDecl>(getCursorDecl(C))) {\r
- ArrayRef<SourceLocation> Locs = ImportD->getIdentifierLocs();\r
- if (!Locs.empty())\r
- return cxloc::translateSourceRange(Ctx,\r
- SourceRange(Locs.front(), Locs.back()));\r
- }\r
- return clang_getNullRange();\r
- }\r
-\r
- // FIXME: A CXCursor_InclusionDirective should give the location of the\r
- // filename, but we don't keep track of this.\r
-\r
- // FIXME: A CXCursor_AnnotateAttr should give the location of the annotation\r
- // but we don't keep track of this.\r
-\r
- // FIXME: A CXCursor_AsmLabelAttr should give the location of the label\r
- // but we don't keep track of this.\r
-\r
- // Default handling, give the location of the cursor.\r
-\r
- if (pieceIndex > 0)\r
- return clang_getNullRange();\r
-\r
- CXSourceLocation CXLoc = clang_getCursorLocation(C);\r
- SourceLocation Loc = cxloc::translateSourceLocation(CXLoc);\r
- return cxloc::translateSourceRange(Ctx, Loc);\r
-}\r
-\r
-CXString clang_getCursorDisplayName(CXCursor C) {\r
- if (!clang_isDeclaration(C.kind))\r
- return clang_getCursorSpelling(C);\r
- \r
- Decl *D = getCursorDecl(C);\r
- if (!D)\r
- return createCXString("");\r
-\r
- PrintingPolicy Policy = getCursorContext(C).getPrintingPolicy();\r
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))\r
- D = FunTmpl->getTemplatedDecl();\r
- \r
- if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {\r
- SmallString<64> Str;\r
- llvm::raw_svector_ostream OS(Str);\r
- OS << *Function;\r
- if (Function->getPrimaryTemplate())\r
- OS << "<>";\r
- OS << "(";\r
- for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) {\r
- if (I)\r
- OS << ", ";\r
- OS << Function->getParamDecl(I)->getType().getAsString(Policy);\r
- }\r
- \r
- if (Function->isVariadic()) {\r
- if (Function->getNumParams())\r
- OS << ", ";\r
- OS << "...";\r
- }\r
- OS << ")";\r
- return createCXString(OS.str());\r
- }\r
- \r
- if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) {\r
- SmallString<64> Str;\r
- llvm::raw_svector_ostream OS(Str);\r
- OS << *ClassTemplate;\r
- OS << "<";\r
- TemplateParameterList *Params = ClassTemplate->getTemplateParameters();\r
- for (unsigned I = 0, N = Params->size(); I != N; ++I) {\r
- if (I)\r
- OS << ", ";\r
- \r
- NamedDecl *Param = Params->getParam(I);\r
- if (Param->getIdentifier()) {\r
- OS << Param->getIdentifier()->getName();\r
- continue;\r
- }\r
- \r
- // There is no parameter name, which makes this tricky. Try to come up\r
- // with something useful that isn't too long.\r
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))\r
- OS << (TTP->wasDeclaredWithTypename()? "typename" : "class");\r
- else if (NonTypeTemplateParmDecl *NTTP\r
- = dyn_cast<NonTypeTemplateParmDecl>(Param))\r
- OS << NTTP->getType().getAsString(Policy);\r
- else\r
- OS << "template<...> class";\r
- }\r
- \r
- OS << ">";\r
- return createCXString(OS.str());\r
- }\r
- \r
- if (ClassTemplateSpecializationDecl *ClassSpec\r
- = dyn_cast<ClassTemplateSpecializationDecl>(D)) {\r
- // If the type was explicitly written, use that.\r
- if (TypeSourceInfo *TSInfo = ClassSpec->getTypeAsWritten())\r
- return createCXString(TSInfo->getType().getAsString(Policy));\r
- \r
- SmallString<64> Str;\r
- llvm::raw_svector_ostream OS(Str);\r
- OS << *ClassSpec;\r
- OS << TemplateSpecializationType::PrintTemplateArgumentList(\r
- ClassSpec->getTemplateArgs().data(),\r
- ClassSpec->getTemplateArgs().size(),\r
- Policy);\r
- return createCXString(OS.str());\r
- }\r
- \r
- return clang_getCursorSpelling(C);\r
-}\r
- \r
-CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {\r
- switch (Kind) {\r
- case CXCursor_FunctionDecl:\r
- return createCXString("FunctionDecl");\r
- case CXCursor_TypedefDecl:\r
- return createCXString("TypedefDecl");\r
- case CXCursor_EnumDecl:\r
- return createCXString("EnumDecl");\r
- case CXCursor_EnumConstantDecl:\r
- return createCXString("EnumConstantDecl");\r
- case CXCursor_StructDecl:\r
- return createCXString("StructDecl");\r
- case CXCursor_UnionDecl:\r
- return createCXString("UnionDecl");\r
- case CXCursor_ClassDecl:\r
- return createCXString("ClassDecl");\r
- case CXCursor_FieldDecl:\r
- return createCXString("FieldDecl");\r
- case CXCursor_VarDecl:\r
- return createCXString("VarDecl");\r
- case CXCursor_ParmDecl:\r
- return createCXString("ParmDecl");\r
- case CXCursor_ObjCInterfaceDecl:\r
- return createCXString("ObjCInterfaceDecl");\r
- case CXCursor_ObjCCategoryDecl:\r
- return createCXString("ObjCCategoryDecl");\r
- case CXCursor_ObjCProtocolDecl:\r
- return createCXString("ObjCProtocolDecl");\r
- case CXCursor_ObjCPropertyDecl:\r
- return createCXString("ObjCPropertyDecl");\r
- case CXCursor_ObjCIvarDecl:\r
- return createCXString("ObjCIvarDecl");\r
- case CXCursor_ObjCInstanceMethodDecl:\r
- return createCXString("ObjCInstanceMethodDecl");\r
- case CXCursor_ObjCClassMethodDecl:\r
- return createCXString("ObjCClassMethodDecl");\r
- case CXCursor_ObjCImplementationDecl:\r
- return createCXString("ObjCImplementationDecl");\r
- case CXCursor_ObjCCategoryImplDecl:\r
- return createCXString("ObjCCategoryImplDecl");\r
- case CXCursor_CXXMethod:\r
- return createCXString("CXXMethod");\r
- case CXCursor_UnexposedDecl:\r
- return createCXString("UnexposedDecl");\r
- case CXCursor_ObjCSuperClassRef:\r
- return createCXString("ObjCSuperClassRef");\r
- case CXCursor_ObjCProtocolRef:\r
- return createCXString("ObjCProtocolRef");\r
- case CXCursor_ObjCClassRef:\r
- return createCXString("ObjCClassRef");\r
- case CXCursor_TypeRef:\r
- return createCXString("TypeRef");\r
- case CXCursor_TemplateRef:\r
- return createCXString("TemplateRef");\r
- case CXCursor_NamespaceRef:\r
- return createCXString("NamespaceRef");\r
- case CXCursor_MemberRef:\r
- return createCXString("MemberRef");\r
- case CXCursor_LabelRef:\r
- return createCXString("LabelRef");\r
- case CXCursor_OverloadedDeclRef:\r
- return createCXString("OverloadedDeclRef");\r
- case CXCursor_VariableRef:\r
- return createCXString("VariableRef");\r
- case CXCursor_IntegerLiteral:\r
- return createCXString("IntegerLiteral");\r
- case CXCursor_FloatingLiteral:\r
- return createCXString("FloatingLiteral");\r
- case CXCursor_ImaginaryLiteral:\r
- return createCXString("ImaginaryLiteral");\r
- case CXCursor_StringLiteral:\r
- return createCXString("StringLiteral");\r
- case CXCursor_CharacterLiteral:\r
- return createCXString("CharacterLiteral");\r
- case CXCursor_ParenExpr:\r
- return createCXString("ParenExpr");\r
- case CXCursor_UnaryOperator:\r
- return createCXString("UnaryOperator");\r
- case CXCursor_ArraySubscriptExpr:\r
- return createCXString("ArraySubscriptExpr");\r
- case CXCursor_BinaryOperator:\r
- return createCXString("BinaryOperator");\r
- case CXCursor_CompoundAssignOperator:\r
- return createCXString("CompoundAssignOperator");\r
- case CXCursor_ConditionalOperator:\r
- return createCXString("ConditionalOperator");\r
- case CXCursor_CStyleCastExpr:\r
- return createCXString("CStyleCastExpr");\r
- case CXCursor_CompoundLiteralExpr:\r
- return createCXString("CompoundLiteralExpr");\r
- case CXCursor_InitListExpr:\r
- return createCXString("InitListExpr");\r
- case CXCursor_AddrLabelExpr:\r
- return createCXString("AddrLabelExpr");\r
- case CXCursor_StmtExpr:\r
- return createCXString("StmtExpr");\r
- case CXCursor_GenericSelectionExpr:\r
- return createCXString("GenericSelectionExpr");\r
- case CXCursor_GNUNullExpr:\r
- return createCXString("GNUNullExpr");\r
- case CXCursor_CXXStaticCastExpr:\r
- return createCXString("CXXStaticCastExpr");\r
- case CXCursor_CXXDynamicCastExpr:\r
- return createCXString("CXXDynamicCastExpr");\r
- case CXCursor_CXXReinterpretCastExpr:\r
- return createCXString("CXXReinterpretCastExpr");\r
- case CXCursor_CXXConstCastExpr:\r
- return createCXString("CXXConstCastExpr");\r
- case CXCursor_CXXFunctionalCastExpr:\r
- return createCXString("CXXFunctionalCastExpr");\r
- case CXCursor_CXXTypeidExpr:\r
- return createCXString("CXXTypeidExpr");\r
- case CXCursor_CXXBoolLiteralExpr:\r
- return createCXString("CXXBoolLiteralExpr");\r
- case CXCursor_CXXNullPtrLiteralExpr:\r
- return createCXString("CXXNullPtrLiteralExpr");\r
- case CXCursor_CXXThisExpr:\r
- return createCXString("CXXThisExpr");\r
- case CXCursor_CXXThrowExpr:\r
- return createCXString("CXXThrowExpr");\r
- case CXCursor_CXXNewExpr:\r
- return createCXString("CXXNewExpr");\r
- case CXCursor_CXXDeleteExpr:\r
- return createCXString("CXXDeleteExpr");\r
- case CXCursor_UnaryExpr:\r
- return createCXString("UnaryExpr");\r
- case CXCursor_ObjCStringLiteral:\r
- return createCXString("ObjCStringLiteral");\r
- case CXCursor_ObjCBoolLiteralExpr:\r
- return createCXString("ObjCBoolLiteralExpr");\r
- case CXCursor_ObjCEncodeExpr:\r
- return createCXString("ObjCEncodeExpr");\r
- case CXCursor_ObjCSelectorExpr:\r
- return createCXString("ObjCSelectorExpr");\r
- case CXCursor_ObjCProtocolExpr:\r
- return createCXString("ObjCProtocolExpr");\r
- case CXCursor_ObjCBridgedCastExpr:\r
- return createCXString("ObjCBridgedCastExpr");\r
- case CXCursor_BlockExpr:\r
- return createCXString("BlockExpr");\r
- case CXCursor_PackExpansionExpr:\r
- return createCXString("PackExpansionExpr");\r
- case CXCursor_SizeOfPackExpr:\r
- return createCXString("SizeOfPackExpr");\r
- case CXCursor_LambdaExpr:\r
- return createCXString("LambdaExpr");\r
- case CXCursor_UnexposedExpr:\r
- return createCXString("UnexposedExpr");\r
- case CXCursor_DeclRefExpr:\r
- return createCXString("DeclRefExpr");\r
- case CXCursor_MemberRefExpr:\r
- return createCXString("MemberRefExpr");\r
- case CXCursor_CallExpr:\r
- return createCXString("CallExpr");\r
- case CXCursor_ObjCMessageExpr:\r
- return createCXString("ObjCMessageExpr");\r
- case CXCursor_UnexposedStmt:\r
- return createCXString("UnexposedStmt");\r
- case CXCursor_DeclStmt:\r
- return createCXString("DeclStmt");\r
- case CXCursor_LabelStmt:\r
- return createCXString("LabelStmt");\r
- case CXCursor_CompoundStmt:\r
- return createCXString("CompoundStmt");\r
- case CXCursor_CaseStmt:\r
- return createCXString("CaseStmt");\r
- case CXCursor_DefaultStmt:\r
- return createCXString("DefaultStmt");\r
- case CXCursor_IfStmt:\r
- return createCXString("IfStmt");\r
- case CXCursor_SwitchStmt:\r
- return createCXString("SwitchStmt");\r
- case CXCursor_WhileStmt:\r
- return createCXString("WhileStmt");\r
- case CXCursor_DoStmt:\r
- return createCXString("DoStmt");\r
- case CXCursor_ForStmt:\r
- return createCXString("ForStmt");\r
- case CXCursor_GotoStmt:\r
- return createCXString("GotoStmt");\r
- case CXCursor_IndirectGotoStmt:\r
- return createCXString("IndirectGotoStmt");\r
- case CXCursor_ContinueStmt:\r
- return createCXString("ContinueStmt");\r
- case CXCursor_BreakStmt:\r
- return createCXString("BreakStmt");\r
- case CXCursor_ReturnStmt:\r
- return createCXString("ReturnStmt");\r
- case CXCursor_GCCAsmStmt:\r
- return createCXString("GCCAsmStmt");\r
- case CXCursor_MSAsmStmt:\r
- return createCXString("MSAsmStmt");\r
- case CXCursor_ObjCAtTryStmt:\r
- return createCXString("ObjCAtTryStmt");\r
- case CXCursor_ObjCAtCatchStmt:\r
- return createCXString("ObjCAtCatchStmt");\r
- case CXCursor_ObjCAtFinallyStmt:\r
- return createCXString("ObjCAtFinallyStmt");\r
- case CXCursor_ObjCAtThrowStmt:\r
- return createCXString("ObjCAtThrowStmt");\r
- case CXCursor_ObjCAtSynchronizedStmt:\r
- return createCXString("ObjCAtSynchronizedStmt");\r
- case CXCursor_ObjCAutoreleasePoolStmt:\r
- return createCXString("ObjCAutoreleasePoolStmt");\r
- case CXCursor_ObjCForCollectionStmt:\r
- return createCXString("ObjCForCollectionStmt");\r
- case CXCursor_CXXCatchStmt:\r
- return createCXString("CXXCatchStmt");\r
- case CXCursor_CXXTryStmt:\r
- return createCXString("CXXTryStmt");\r
- case CXCursor_CXXForRangeStmt:\r
- return createCXString("CXXForRangeStmt");\r
- case CXCursor_SEHTryStmt:\r
- return createCXString("SEHTryStmt");\r
- case CXCursor_SEHExceptStmt:\r
- return createCXString("SEHExceptStmt");\r
- case CXCursor_SEHFinallyStmt:\r
- return createCXString("SEHFinallyStmt");\r
- case CXCursor_NullStmt:\r
- return createCXString("NullStmt");\r
- case CXCursor_InvalidFile:\r
- return createCXString("InvalidFile");\r
- case CXCursor_InvalidCode:\r
- return createCXString("InvalidCode");\r
- case CXCursor_NoDeclFound:\r
- return createCXString("NoDeclFound");\r
- case CXCursor_NotImplemented:\r
- return createCXString("NotImplemented");\r
- case CXCursor_TranslationUnit:\r
- return createCXString("TranslationUnit");\r
- case CXCursor_UnexposedAttr:\r
- return createCXString("UnexposedAttr");\r
- case CXCursor_IBActionAttr:\r
- return createCXString("attribute(ibaction)");\r
- case CXCursor_IBOutletAttr:\r
- return createCXString("attribute(iboutlet)");\r
- case CXCursor_IBOutletCollectionAttr:\r
- return createCXString("attribute(iboutletcollection)");\r
- case CXCursor_CXXFinalAttr:\r
- return createCXString("attribute(final)");\r
- case CXCursor_CXXOverrideAttr:\r
- return createCXString("attribute(override)");\r
- case CXCursor_AnnotateAttr:\r
- return createCXString("attribute(annotate)");\r
- case CXCursor_AsmLabelAttr:\r
- return createCXString("asm label");\r
- case CXCursor_PreprocessingDirective:\r
- return createCXString("preprocessing directive");\r
- case CXCursor_MacroDefinition:\r
- return createCXString("macro definition");\r
- case CXCursor_MacroExpansion:\r
- return createCXString("macro expansion");\r
- case CXCursor_InclusionDirective:\r
- return createCXString("inclusion directive");\r
- case CXCursor_Namespace:\r
- return createCXString("Namespace");\r
- case CXCursor_LinkageSpec:\r
- return createCXString("LinkageSpec");\r
- case CXCursor_CXXBaseSpecifier:\r
- return createCXString("C++ base class specifier"); \r
- case CXCursor_Constructor:\r
- return createCXString("CXXConstructor");\r
- case CXCursor_Destructor:\r
- return createCXString("CXXDestructor");\r
- case CXCursor_ConversionFunction:\r
- return createCXString("CXXConversion");\r
- case CXCursor_TemplateTypeParameter:\r
- return createCXString("TemplateTypeParameter");\r
- case CXCursor_NonTypeTemplateParameter:\r
- return createCXString("NonTypeTemplateParameter");\r
- case CXCursor_TemplateTemplateParameter:\r
- return createCXString("TemplateTemplateParameter");\r
- case CXCursor_FunctionTemplate:\r
- return createCXString("FunctionTemplate");\r
- case CXCursor_ClassTemplate:\r
- return createCXString("ClassTemplate");\r
- case CXCursor_ClassTemplatePartialSpecialization:\r
- return createCXString("ClassTemplatePartialSpecialization");\r
- case CXCursor_NamespaceAlias:\r
- return createCXString("NamespaceAlias");\r
- case CXCursor_UsingDirective:\r
- return createCXString("UsingDirective");\r
- case CXCursor_UsingDeclaration:\r
- return createCXString("UsingDeclaration");\r
- case CXCursor_TypeAliasDecl:\r
- return createCXString("TypeAliasDecl");\r
- case CXCursor_ObjCSynthesizeDecl:\r
- return createCXString("ObjCSynthesizeDecl");\r
- case CXCursor_ObjCDynamicDecl:\r
- return createCXString("ObjCDynamicDecl");\r
- case CXCursor_CXXAccessSpecifier:\r
- return createCXString("CXXAccessSpecifier");\r
- case CXCursor_ModuleImportDecl:\r
- return createCXString("ModuleImport");\r
- }\r
-\r
- llvm_unreachable("Unhandled CXCursorKind");\r
-}\r
-\r
-struct GetCursorData {\r
- SourceLocation TokenBeginLoc;\r
- bool PointsAtMacroArgExpansion;\r
- bool VisitedObjCPropertyImplDecl;\r
- SourceLocation VisitedDeclaratorDeclStartLoc;\r
- CXCursor &BestCursor;\r
-\r
- GetCursorData(SourceManager &SM,\r
- SourceLocation tokenBegin, CXCursor &outputCursor)\r
- : TokenBeginLoc(tokenBegin), BestCursor(outputCursor) {\r
- PointsAtMacroArgExpansion = SM.isMacroArgExpansion(tokenBegin);\r
- VisitedObjCPropertyImplDecl = false;\r
- }\r
-};\r
-\r
-static enum CXChildVisitResult GetCursorVisitor(CXCursor cursor,\r
- CXCursor parent,\r
- CXClientData client_data) {\r
- GetCursorData *Data = static_cast<GetCursorData *>(client_data);\r
- CXCursor *BestCursor = &Data->BestCursor;\r
-\r
- // If we point inside a macro argument we should provide info of what the\r
- // token is so use the actual cursor, don't replace it with a macro expansion\r
- // cursor.\r
- if (cursor.kind == CXCursor_MacroExpansion && Data->PointsAtMacroArgExpansion)\r
- return CXChildVisit_Recurse;\r
- \r
- if (clang_isDeclaration(cursor.kind)) {\r
- // Avoid having the implicit methods override the property decls.\r
- if (ObjCMethodDecl *MD\r
- = dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {\r
- if (MD->isImplicit())\r
- return CXChildVisit_Break;\r
-\r
- } else if (ObjCInterfaceDecl *ID\r
- = dyn_cast_or_null<ObjCInterfaceDecl>(getCursorDecl(cursor))) {\r
- // Check that when we have multiple @class references in the same line,\r
- // that later ones do not override the previous ones.\r
- // If we have:\r
- // @class Foo, Bar;\r
- // source ranges for both start at '@', so 'Bar' will end up overriding\r
- // 'Foo' even though the cursor location was at 'Foo'.\r
- if (BestCursor->kind == CXCursor_ObjCInterfaceDecl ||\r
- BestCursor->kind == CXCursor_ObjCClassRef)\r
- if (ObjCInterfaceDecl *PrevID\r
- = dyn_cast_or_null<ObjCInterfaceDecl>(getCursorDecl(*BestCursor))){\r
- if (PrevID != ID &&\r
- !PrevID->isThisDeclarationADefinition() &&\r
- !ID->isThisDeclarationADefinition())\r
- return CXChildVisit_Break;\r
- }\r
-\r
- } else if (DeclaratorDecl *DD\r
- = dyn_cast_or_null<DeclaratorDecl>(getCursorDecl(cursor))) {\r
- SourceLocation StartLoc = DD->getSourceRange().getBegin();\r
- // Check that when we have multiple declarators in the same line,\r
- // that later ones do not override the previous ones.\r
- // If we have:\r
- // int Foo, Bar;\r
- // source ranges for both start at 'int', so 'Bar' will end up overriding\r
- // 'Foo' even though the cursor location was at 'Foo'.\r
- if (Data->VisitedDeclaratorDeclStartLoc == StartLoc)\r
- return CXChildVisit_Break;\r
- Data->VisitedDeclaratorDeclStartLoc = StartLoc;\r
-\r
- } else if (ObjCPropertyImplDecl *PropImp\r
- = dyn_cast_or_null<ObjCPropertyImplDecl>(getCursorDecl(cursor))) {\r
- (void)PropImp;\r
- // Check that when we have multiple @synthesize in the same line,\r
- // that later ones do not override the previous ones.\r
- // If we have:\r
- // @synthesize Foo, Bar;\r
- // source ranges for both start at '@', so 'Bar' will end up overriding\r
- // 'Foo' even though the cursor location was at 'Foo'.\r
- if (Data->VisitedObjCPropertyImplDecl)\r
- return CXChildVisit_Break;\r
- Data->VisitedObjCPropertyImplDecl = true;\r
- }\r
- }\r
-\r
- if (clang_isExpression(cursor.kind) &&\r
- clang_isDeclaration(BestCursor->kind)) {\r
- if (Decl *D = getCursorDecl(*BestCursor)) {\r
- // Avoid having the cursor of an expression replace the declaration cursor\r
- // when the expression source range overlaps the declaration range.\r
- // This can happen for C++ constructor expressions whose range generally\r
- // include the variable declaration, e.g.:\r
- // MyCXXClass foo; // Make sure pointing at 'foo' returns a VarDecl cursor.\r
- if (D->getLocation().isValid() && Data->TokenBeginLoc.isValid() &&\r
- D->getLocation() == Data->TokenBeginLoc)\r
- return CXChildVisit_Break;\r
- }\r
- }\r
-\r
- // If our current best cursor is the construction of a temporary object, \r
- // don't replace that cursor with a type reference, because we want \r
- // clang_getCursor() to point at the constructor.\r
- if (clang_isExpression(BestCursor->kind) &&\r
- isa<CXXTemporaryObjectExpr>(getCursorExpr(*BestCursor)) &&\r
- cursor.kind == CXCursor_TypeRef) {\r
- // Keep the cursor pointing at CXXTemporaryObjectExpr but also mark it\r
- // as having the actual point on the type reference.\r
- *BestCursor = getTypeRefedCallExprCursor(*BestCursor);\r
- return CXChildVisit_Recurse;\r
- }\r
- \r
- *BestCursor = cursor;\r
- return CXChildVisit_Recurse;\r
-}\r
-\r
-CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {\r
- if (!TU)\r
- return clang_getNullCursor();\r
-\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);\r
- ASTUnit::ConcurrencyCheck Check(*CXXUnit);\r
-\r
- SourceLocation SLoc = cxloc::translateSourceLocation(Loc);\r
- CXCursor Result = cxcursor::getCursor(TU, SLoc);\r
-\r
- bool Logging = getenv("LIBCLANG_LOGGING"); \r
- if (Logging) {\r
- CXFile SearchFile;\r
- unsigned SearchLine, SearchColumn;\r
- CXFile ResultFile;\r
- unsigned ResultLine, ResultColumn;\r
- CXString SearchFileName, ResultFileName, KindSpelling, USR;\r
- const char *IsDef = clang_isCursorDefinition(Result)? " (Definition)" : "";\r
- CXSourceLocation ResultLoc = clang_getCursorLocation(Result);\r
- \r
- clang_getExpansionLocation(Loc, &SearchFile, &SearchLine, &SearchColumn, 0);\r
- clang_getExpansionLocation(ResultLoc, &ResultFile, &ResultLine,\r
- &ResultColumn, 0);\r
- SearchFileName = clang_getFileName(SearchFile);\r
- ResultFileName = clang_getFileName(ResultFile);\r
- KindSpelling = clang_getCursorKindSpelling(Result.kind);\r
- USR = clang_getCursorUSR(Result);\r
- fprintf(stderr, "clang_getCursor(%s:%d:%d) = %s(%s:%d:%d):%s%s\n",\r
- clang_getCString(SearchFileName), SearchLine, SearchColumn,\r
- clang_getCString(KindSpelling),\r
- clang_getCString(ResultFileName), ResultLine, ResultColumn,\r
- clang_getCString(USR), IsDef);\r
- clang_disposeString(SearchFileName);\r
- clang_disposeString(ResultFileName);\r
- clang_disposeString(KindSpelling);\r
- clang_disposeString(USR);\r
- \r
- CXCursor Definition = clang_getCursorDefinition(Result);\r
- if (!clang_equalCursors(Definition, clang_getNullCursor())) {\r
- CXSourceLocation DefinitionLoc = clang_getCursorLocation(Definition);\r
- CXString DefinitionKindSpelling\r
- = clang_getCursorKindSpelling(Definition.kind);\r
- CXFile DefinitionFile;\r
- unsigned DefinitionLine, DefinitionColumn;\r
- clang_getExpansionLocation(DefinitionLoc, &DefinitionFile,\r
- &DefinitionLine, &DefinitionColumn, 0);\r
- CXString DefinitionFileName = clang_getFileName(DefinitionFile);\r
- fprintf(stderr, " -> %s(%s:%d:%d)\n",\r
- clang_getCString(DefinitionKindSpelling),\r
- clang_getCString(DefinitionFileName),\r
- DefinitionLine, DefinitionColumn);\r
- clang_disposeString(DefinitionFileName);\r
- clang_disposeString(DefinitionKindSpelling);\r
- }\r
- }\r
-\r
- return Result;\r
-}\r
-\r
-CXCursor clang_getNullCursor(void) {\r
- return MakeCXCursorInvalid(CXCursor_InvalidFile);\r
-}\r
-\r
-unsigned clang_equalCursors(CXCursor X, CXCursor Y) {\r
- return X == Y;\r
-}\r
-\r
-unsigned clang_hashCursor(CXCursor C) {\r
- unsigned Index = 0;\r
- if (clang_isExpression(C.kind) || clang_isStatement(C.kind))\r
- Index = 1;\r
- \r
- return llvm::DenseMapInfo<std::pair<unsigned, void*> >::getHashValue(\r
- std::make_pair(C.kind, C.data[Index]));\r
-}\r
-\r
-unsigned clang_isInvalid(enum CXCursorKind K) {\r
- return K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid;\r
-}\r
-\r
-unsigned clang_isDeclaration(enum CXCursorKind K) {\r
- return (K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl) ||\r
- (K >= CXCursor_FirstExtraDecl && K <= CXCursor_LastExtraDecl);\r
-}\r
-\r
-unsigned clang_isReference(enum CXCursorKind K) {\r
- return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;\r
-}\r
-\r
-unsigned clang_isExpression(enum CXCursorKind K) {\r
- return K >= CXCursor_FirstExpr && K <= CXCursor_LastExpr;\r
-}\r
-\r
-unsigned clang_isStatement(enum CXCursorKind K) {\r
- return K >= CXCursor_FirstStmt && K <= CXCursor_LastStmt;\r
-}\r
-\r
-unsigned clang_isAttribute(enum CXCursorKind K) {\r
- return K >= CXCursor_FirstAttr && K <= CXCursor_LastAttr;\r
-}\r
-\r
-unsigned clang_isTranslationUnit(enum CXCursorKind K) {\r
- return K == CXCursor_TranslationUnit;\r
-}\r
-\r
-unsigned clang_isPreprocessing(enum CXCursorKind K) {\r
- return K >= CXCursor_FirstPreprocessing && K <= CXCursor_LastPreprocessing;\r
-}\r
- \r
-unsigned clang_isUnexposed(enum CXCursorKind K) {\r
- switch (K) {\r
- case CXCursor_UnexposedDecl:\r
- case CXCursor_UnexposedExpr:\r
- case CXCursor_UnexposedStmt:\r
- case CXCursor_UnexposedAttr:\r
- return true;\r
- default:\r
- return false;\r
- }\r
-}\r
-\r
-CXCursorKind clang_getCursorKind(CXCursor C) {\r
- return C.kind;\r
-}\r
-\r
-CXSourceLocation clang_getCursorLocation(CXCursor C) {\r
- if (clang_isReference(C.kind)) {\r
- switch (C.kind) {\r
- case CXCursor_ObjCSuperClassRef: {\r
- std::pair<ObjCInterfaceDecl *, SourceLocation> P\r
- = getCursorObjCSuperClassRef(C);\r
- return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);\r
- }\r
-\r
- case CXCursor_ObjCProtocolRef: {\r
- std::pair<ObjCProtocolDecl *, SourceLocation> P\r
- = getCursorObjCProtocolRef(C);\r
- return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);\r
- }\r
-\r
- case CXCursor_ObjCClassRef: {\r
- std::pair<ObjCInterfaceDecl *, SourceLocation> P\r
- = getCursorObjCClassRef(C);\r
- return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);\r
- }\r
-\r
- case CXCursor_TypeRef: {\r
- std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);\r
- return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);\r
- }\r
-\r
- case CXCursor_TemplateRef: {\r
- std::pair<TemplateDecl *, SourceLocation> P = getCursorTemplateRef(C);\r
- return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);\r
- }\r
-\r
- case CXCursor_NamespaceRef: {\r
- std::pair<NamedDecl *, SourceLocation> P = getCursorNamespaceRef(C);\r
- return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);\r
- }\r
-\r
- case CXCursor_MemberRef: {\r
- std::pair<FieldDecl *, SourceLocation> P = getCursorMemberRef(C);\r
- return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);\r
- }\r
-\r
- case CXCursor_VariableRef: {\r
- std::pair<VarDecl *, SourceLocation> P = getCursorVariableRef(C);\r
- return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);\r
- }\r
-\r
- case CXCursor_CXXBaseSpecifier: {\r
- CXXBaseSpecifier *BaseSpec = getCursorCXXBaseSpecifier(C);\r
- if (!BaseSpec)\r
- return clang_getNullLocation();\r
- \r
- if (TypeSourceInfo *TSInfo = BaseSpec->getTypeSourceInfo())\r
- return cxloc::translateSourceLocation(getCursorContext(C),\r
- TSInfo->getTypeLoc().getBeginLoc());\r
- \r
- return cxloc::translateSourceLocation(getCursorContext(C),\r
- BaseSpec->getLocStart());\r
- }\r
-\r
- case CXCursor_LabelRef: {\r
- std::pair<LabelStmt *, SourceLocation> P = getCursorLabelRef(C);\r
- return cxloc::translateSourceLocation(getCursorContext(C), P.second);\r
- }\r
-\r
- case CXCursor_OverloadedDeclRef:\r
- return cxloc::translateSourceLocation(getCursorContext(C),\r
- getCursorOverloadedDeclRef(C).second);\r
-\r
- default:\r
- // FIXME: Need a way to enumerate all non-reference cases.\r
- llvm_unreachable("Missed a reference kind");\r
- }\r
- }\r
-\r
- if (clang_isExpression(C.kind))\r
- return cxloc::translateSourceLocation(getCursorContext(C),\r
- getLocationFromExpr(getCursorExpr(C)));\r
-\r
- if (clang_isStatement(C.kind))\r
- return cxloc::translateSourceLocation(getCursorContext(C),\r
- getCursorStmt(C)->getLocStart());\r
-\r
- if (C.kind == CXCursor_PreprocessingDirective) {\r
- SourceLocation L = cxcursor::getCursorPreprocessingDirective(C).getBegin();\r
- return cxloc::translateSourceLocation(getCursorContext(C), L);\r
- }\r
-\r
- if (C.kind == CXCursor_MacroExpansion) {\r
- SourceLocation L\r
- = cxcursor::getCursorMacroExpansion(C)->getSourceRange().getBegin();\r
- return cxloc::translateSourceLocation(getCursorContext(C), L);\r
- }\r
-\r
- if (C.kind == CXCursor_MacroDefinition) {\r
- SourceLocation L = cxcursor::getCursorMacroDefinition(C)->getLocation();\r
- return cxloc::translateSourceLocation(getCursorContext(C), L);\r
- }\r
-\r
- if (C.kind == CXCursor_InclusionDirective) {\r
- SourceLocation L\r
- = cxcursor::getCursorInclusionDirective(C)->getSourceRange().getBegin();\r
- return cxloc::translateSourceLocation(getCursorContext(C), L);\r
- }\r
-\r
- if (!clang_isDeclaration(C.kind))\r
- return clang_getNullLocation();\r
-\r
- Decl *D = getCursorDecl(C);\r
- if (!D)\r
- return clang_getNullLocation();\r
-\r
- SourceLocation Loc = D->getLocation();\r
- // FIXME: Multiple variables declared in a single declaration\r
- // currently lack the information needed to correctly determine their\r
- // ranges when accounting for the type-specifier. We use context\r
- // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,\r
- // and if so, whether it is the first decl.\r
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {\r
- if (!cxcursor::isFirstInDeclGroup(C))\r
- Loc = VD->getLocation();\r
- }\r
-\r
- // For ObjC methods, give the start location of the method name.\r
- if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))\r
- Loc = MD->getSelectorStartLoc();\r
-\r
- return cxloc::translateSourceLocation(getCursorContext(C), Loc);\r
-}\r
-\r
-} // end extern "C"\r
-\r
-CXCursor cxcursor::getCursor(CXTranslationUnit TU, SourceLocation SLoc) {\r
- assert(TU);\r
-\r
- // Guard against an invalid SourceLocation, or we may assert in one\r
- // of the following calls.\r
- if (SLoc.isInvalid())\r
- return clang_getNullCursor();\r
-\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);\r
-\r
- // Translate the given source location to make it point at the beginning of\r
- // the token under the cursor.\r
- SLoc = Lexer::GetBeginningOfToken(SLoc, CXXUnit->getSourceManager(),\r
- CXXUnit->getASTContext().getLangOpts());\r
- \r
- CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);\r
- if (SLoc.isValid()) {\r
- GetCursorData ResultData(CXXUnit->getSourceManager(), SLoc, Result);\r
- CursorVisitor CursorVis(TU, GetCursorVisitor, &ResultData,\r
- /*VisitPreprocessorLast=*/true, \r
- /*VisitIncludedEntities=*/false,\r
- SourceLocation(SLoc));\r
- CursorVis.visitFileRegion();\r
- }\r
-\r
- return Result;\r
-}\r
-\r
-static SourceRange getRawCursorExtent(CXCursor C) {\r
- if (clang_isReference(C.kind)) {\r
- switch (C.kind) {\r
- case CXCursor_ObjCSuperClassRef:\r
- return getCursorObjCSuperClassRef(C).second;\r
-\r
- case CXCursor_ObjCProtocolRef:\r
- return getCursorObjCProtocolRef(C).second;\r
-\r
- case CXCursor_ObjCClassRef:\r
- return getCursorObjCClassRef(C).second;\r
-\r
- case CXCursor_TypeRef:\r
- return getCursorTypeRef(C).second;\r
-\r
- case CXCursor_TemplateRef:\r
- return getCursorTemplateRef(C).second;\r
-\r
- case CXCursor_NamespaceRef:\r
- return getCursorNamespaceRef(C).second;\r
-\r
- case CXCursor_MemberRef:\r
- return getCursorMemberRef(C).second;\r
-\r
- case CXCursor_CXXBaseSpecifier:\r
- return getCursorCXXBaseSpecifier(C)->getSourceRange();\r
-\r
- case CXCursor_LabelRef:\r
- return getCursorLabelRef(C).second;\r
-\r
- case CXCursor_OverloadedDeclRef:\r
- return getCursorOverloadedDeclRef(C).second;\r
-\r
- case CXCursor_VariableRef:\r
- return getCursorVariableRef(C).second;\r
- \r
- default:\r
- // FIXME: Need a way to enumerate all non-reference cases.\r
- llvm_unreachable("Missed a reference kind");\r
- }\r
- }\r
-\r
- if (clang_isExpression(C.kind))\r
- return getCursorExpr(C)->getSourceRange();\r
-\r
- if (clang_isStatement(C.kind))\r
- return getCursorStmt(C)->getSourceRange();\r
-\r
- if (clang_isAttribute(C.kind))\r
- return getCursorAttr(C)->getRange();\r
-\r
- if (C.kind == CXCursor_PreprocessingDirective)\r
- return cxcursor::getCursorPreprocessingDirective(C);\r
-\r
- if (C.kind == CXCursor_MacroExpansion) {\r
- ASTUnit *TU = getCursorASTUnit(C);\r
- SourceRange Range = cxcursor::getCursorMacroExpansion(C)->getSourceRange();\r
- return TU->mapRangeFromPreamble(Range);\r
- }\r
-\r
- if (C.kind == CXCursor_MacroDefinition) {\r
- ASTUnit *TU = getCursorASTUnit(C);\r
- SourceRange Range = cxcursor::getCursorMacroDefinition(C)->getSourceRange();\r
- return TU->mapRangeFromPreamble(Range);\r
- }\r
-\r
- if (C.kind == CXCursor_InclusionDirective) {\r
- ASTUnit *TU = getCursorASTUnit(C);\r
- SourceRange Range = cxcursor::getCursorInclusionDirective(C)->getSourceRange();\r
- return TU->mapRangeFromPreamble(Range);\r
- }\r
-\r
- if (C.kind == CXCursor_TranslationUnit) {\r
- ASTUnit *TU = getCursorASTUnit(C);\r
- FileID MainID = TU->getSourceManager().getMainFileID();\r
- SourceLocation Start = TU->getSourceManager().getLocForStartOfFile(MainID);\r
- SourceLocation End = TU->getSourceManager().getLocForEndOfFile(MainID);\r
- return SourceRange(Start, End);\r
- }\r
-\r
- if (clang_isDeclaration(C.kind)) {\r
- Decl *D = cxcursor::getCursorDecl(C);\r
- if (!D)\r
- return SourceRange();\r
-\r
- SourceRange R = D->getSourceRange();\r
- // FIXME: Multiple variables declared in a single declaration\r
- // currently lack the information needed to correctly determine their\r
- // ranges when accounting for the type-specifier. We use context\r
- // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,\r
- // and if so, whether it is the first decl.\r
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {\r
- if (!cxcursor::isFirstInDeclGroup(C))\r
- R.setBegin(VD->getLocation());\r
- }\r
- return R;\r
- }\r
- return SourceRange();\r
-}\r
-\r
-/// \brief Retrieves the "raw" cursor extent, which is then extended to include\r
-/// the decl-specifier-seq for declarations.\r
-static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr) {\r
- if (clang_isDeclaration(C.kind)) {\r
- Decl *D = cxcursor::getCursorDecl(C);\r
- if (!D)\r
- return SourceRange();\r
-\r
- SourceRange R = D->getSourceRange();\r
-\r
- // Adjust the start of the location for declarations preceded by\r
- // declaration specifiers.\r
- SourceLocation StartLoc;\r
- if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {\r
- if (TypeSourceInfo *TI = DD->getTypeSourceInfo())\r
- StartLoc = TI->getTypeLoc().getLocStart();\r
- } else if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(D)) {\r
- if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())\r
- StartLoc = TI->getTypeLoc().getLocStart();\r
- }\r
-\r
- if (StartLoc.isValid() && R.getBegin().isValid() &&\r
- SrcMgr.isBeforeInTranslationUnit(StartLoc, R.getBegin()))\r
- R.setBegin(StartLoc);\r
-\r
- // FIXME: Multiple variables declared in a single declaration\r
- // currently lack the information needed to correctly determine their\r
- // ranges when accounting for the type-specifier. We use context\r
- // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,\r
- // and if so, whether it is the first decl.\r
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {\r
- if (!cxcursor::isFirstInDeclGroup(C))\r
- R.setBegin(VD->getLocation());\r
- }\r
-\r
- return R; \r
- }\r
- \r
- return getRawCursorExtent(C);\r
-}\r
-\r
-extern "C" {\r
-\r
-CXSourceRange clang_getCursorExtent(CXCursor C) {\r
- SourceRange R = getRawCursorExtent(C);\r
- if (R.isInvalid())\r
- return clang_getNullRange();\r
-\r
- return cxloc::translateSourceRange(getCursorContext(C), R);\r
-}\r
-\r
-CXCursor clang_getCursorReferenced(CXCursor C) {\r
- if (clang_isInvalid(C.kind))\r
- return clang_getNullCursor();\r
-\r
- CXTranslationUnit tu = getCursorTU(C);\r
- if (clang_isDeclaration(C.kind)) {\r
- Decl *D = getCursorDecl(C);\r
- if (!D)\r
- return clang_getNullCursor();\r
- if (UsingDecl *Using = dyn_cast<UsingDecl>(D))\r
- return MakeCursorOverloadedDeclRef(Using, D->getLocation(), tu);\r
- if (ObjCPropertyImplDecl *PropImpl =dyn_cast<ObjCPropertyImplDecl>(D))\r
- if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())\r
- return MakeCXCursor(Property, tu);\r
- \r
- return C;\r
- }\r
- \r
- if (clang_isExpression(C.kind)) {\r
- Expr *E = getCursorExpr(C);\r
- Decl *D = getDeclFromExpr(E);\r
- if (D) {\r
- CXCursor declCursor = MakeCXCursor(D, tu);\r
- declCursor = getSelectorIdentifierCursor(getSelectorIdentifierIndex(C),\r
- declCursor);\r
- return declCursor;\r
- }\r
- \r
- if (OverloadExpr *Ovl = dyn_cast_or_null<OverloadExpr>(E))\r
- return MakeCursorOverloadedDeclRef(Ovl, tu);\r
- \r
- return clang_getNullCursor();\r
- }\r
-\r
- if (clang_isStatement(C.kind)) {\r
- Stmt *S = getCursorStmt(C);\r
- if (GotoStmt *Goto = dyn_cast_or_null<GotoStmt>(S))\r
- if (LabelDecl *label = Goto->getLabel())\r
- if (LabelStmt *labelS = label->getStmt())\r
- return MakeCXCursor(labelS, getCursorDecl(C), tu);\r
-\r
- return clang_getNullCursor();\r
- }\r
- \r
- if (C.kind == CXCursor_MacroExpansion) {\r
- if (MacroDefinition *Def = getCursorMacroExpansion(C)->getDefinition())\r
- return MakeMacroDefinitionCursor(Def, tu);\r
- }\r
-\r
- if (!clang_isReference(C.kind))\r
- return clang_getNullCursor();\r
-\r
- switch (C.kind) {\r
- case CXCursor_ObjCSuperClassRef:\r
- return MakeCXCursor(getCursorObjCSuperClassRef(C).first, tu);\r
-\r
- case CXCursor_ObjCProtocolRef: {\r
- ObjCProtocolDecl *Prot = getCursorObjCProtocolRef(C).first;\r
- if (ObjCProtocolDecl *Def = Prot->getDefinition())\r
- return MakeCXCursor(Def, tu);\r
-\r
- return MakeCXCursor(Prot, tu);\r
- }\r
-\r
- case CXCursor_ObjCClassRef: {\r
- ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;\r
- if (ObjCInterfaceDecl *Def = Class->getDefinition())\r
- return MakeCXCursor(Def, tu);\r
-\r
- return MakeCXCursor(Class, tu);\r
- }\r
-\r
- case CXCursor_TypeRef:\r
- return MakeCXCursor(getCursorTypeRef(C).first, tu );\r
-\r
- case CXCursor_TemplateRef:\r
- return MakeCXCursor(getCursorTemplateRef(C).first, tu );\r
-\r
- case CXCursor_NamespaceRef:\r
- return MakeCXCursor(getCursorNamespaceRef(C).first, tu );\r
-\r
- case CXCursor_MemberRef:\r
- return MakeCXCursor(getCursorMemberRef(C).first, tu );\r
-\r
- case CXCursor_CXXBaseSpecifier: {\r
- CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C);\r
- return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(),\r
- tu ));\r
- }\r
-\r
- case CXCursor_LabelRef:\r
- // FIXME: We end up faking the "parent" declaration here because we\r
- // don't want to make CXCursor larger.\r
- return MakeCXCursor(getCursorLabelRef(C).first, \r
- static_cast<ASTUnit*>(tu->TUData)->getASTContext()\r
- .getTranslationUnitDecl(),\r
- tu);\r
-\r
- case CXCursor_OverloadedDeclRef:\r
- return C;\r
- \r
- case CXCursor_VariableRef:\r
- return MakeCXCursor(getCursorVariableRef(C).first, tu);\r
-\r
- default:\r
- // We would prefer to enumerate all non-reference cursor kinds here.\r
- llvm_unreachable("Unhandled reference cursor kind");\r
- }\r
-}\r
-\r
-CXCursor clang_getCursorDefinition(CXCursor C) {\r
- if (clang_isInvalid(C.kind))\r
- return clang_getNullCursor();\r
-\r
- CXTranslationUnit TU = getCursorTU(C);\r
-\r
- bool WasReference = false;\r
- if (clang_isReference(C.kind) || clang_isExpression(C.kind)) {\r
- C = clang_getCursorReferenced(C);\r
- WasReference = true;\r
- }\r
-\r
- if (C.kind == CXCursor_MacroExpansion)\r
- return clang_getCursorReferenced(C);\r
-\r
- if (!clang_isDeclaration(C.kind))\r
- return clang_getNullCursor();\r
-\r
- Decl *D = getCursorDecl(C);\r
- if (!D)\r
- return clang_getNullCursor();\r
-\r
- switch (D->getKind()) {\r
- // Declaration kinds that don't really separate the notions of\r
- // declaration and definition.\r
- case Decl::Namespace:\r
- case Decl::Typedef:\r
- case Decl::TypeAlias:\r
- case Decl::TypeAliasTemplate:\r
- case Decl::TemplateTypeParm:\r
- case Decl::EnumConstant:\r
- case Decl::Field:\r
- case Decl::IndirectField:\r
- case Decl::ObjCIvar:\r
- case Decl::ObjCAtDefsField:\r
- case Decl::ImplicitParam:\r
- case Decl::ParmVar:\r
- case Decl::NonTypeTemplateParm:\r
- case Decl::TemplateTemplateParm:\r
- case Decl::ObjCCategoryImpl:\r
- case Decl::ObjCImplementation:\r
- case Decl::AccessSpec:\r
- case Decl::LinkageSpec:\r
- case Decl::ObjCPropertyImpl:\r
- case Decl::FileScopeAsm:\r
- case Decl::StaticAssert:\r
- case Decl::Block:\r
- case Decl::Label: // FIXME: Is this right??\r
- case Decl::ClassScopeFunctionSpecialization:\r
- case Decl::Import:\r
- return C;\r
-\r
- // Declaration kinds that don't make any sense here, but are\r
- // nonetheless harmless.\r
- case Decl::TranslationUnit:\r
- break;\r
-\r
- // Declaration kinds for which the definition is not resolvable.\r
- case Decl::UnresolvedUsingTypename:\r
- case Decl::UnresolvedUsingValue:\r
- break;\r
-\r
- case Decl::UsingDirective:\r
- return MakeCXCursor(cast<UsingDirectiveDecl>(D)->getNominatedNamespace(),\r
- TU);\r
-\r
- case Decl::NamespaceAlias:\r
- return MakeCXCursor(cast<NamespaceAliasDecl>(D)->getNamespace(), TU);\r
-\r
- case Decl::Enum:\r
- case Decl::Record:\r
- case Decl::CXXRecord:\r
- case Decl::ClassTemplateSpecialization:\r
- case Decl::ClassTemplatePartialSpecialization:\r
- if (TagDecl *Def = cast<TagDecl>(D)->getDefinition())\r
- return MakeCXCursor(Def, TU);\r
- return clang_getNullCursor();\r
-\r
- case Decl::Function:\r
- case Decl::CXXMethod:\r
- case Decl::CXXConstructor:\r
- case Decl::CXXDestructor:\r
- case Decl::CXXConversion: {\r
- const FunctionDecl *Def = 0;\r
- if (cast<FunctionDecl>(D)->getBody(Def))\r
- return MakeCXCursor(const_cast<FunctionDecl *>(Def), TU);\r
- return clang_getNullCursor();\r
- }\r
-\r
- case Decl::Var: {\r
- // Ask the variable if it has a definition.\r
- if (VarDecl *Def = cast<VarDecl>(D)->getDefinition())\r
- return MakeCXCursor(Def, TU);\r
- return clang_getNullCursor();\r
- }\r
-\r
- case Decl::FunctionTemplate: {\r
- const FunctionDecl *Def = 0;\r
- if (cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->getBody(Def))\r
- return MakeCXCursor(Def->getDescribedFunctionTemplate(), TU);\r
- return clang_getNullCursor();\r
- }\r
-\r
- case Decl::ClassTemplate: {\r
- if (RecordDecl *Def = cast<ClassTemplateDecl>(D)->getTemplatedDecl()\r
- ->getDefinition())\r
- return MakeCXCursor(cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),\r
- TU);\r
- return clang_getNullCursor();\r
- }\r
-\r
- case Decl::Using:\r
- return MakeCursorOverloadedDeclRef(cast<UsingDecl>(D), \r
- D->getLocation(), TU);\r
-\r
- case Decl::UsingShadow:\r
- return clang_getCursorDefinition(\r
- MakeCXCursor(cast<UsingShadowDecl>(D)->getTargetDecl(),\r
- TU));\r
-\r
- case Decl::ObjCMethod: {\r
- ObjCMethodDecl *Method = cast<ObjCMethodDecl>(D);\r
- if (Method->isThisDeclarationADefinition())\r
- return C;\r
-\r
- // Dig out the method definition in the associated\r
- // @implementation, if we have it.\r
- // FIXME: The ASTs should make finding the definition easier.\r
- if (ObjCInterfaceDecl *Class\r
- = dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext()))\r
- if (ObjCImplementationDecl *ClassImpl = Class->getImplementation())\r
- if (ObjCMethodDecl *Def = ClassImpl->getMethod(Method->getSelector(),\r
- Method->isInstanceMethod()))\r
- if (Def->isThisDeclarationADefinition())\r
- return MakeCXCursor(Def, TU);\r
-\r
- return clang_getNullCursor();\r
- }\r
-\r
- case Decl::ObjCCategory:\r
- if (ObjCCategoryImplDecl *Impl\r
- = cast<ObjCCategoryDecl>(D)->getImplementation())\r
- return MakeCXCursor(Impl, TU);\r
- return clang_getNullCursor();\r
-\r
- case Decl::ObjCProtocol:\r
- if (ObjCProtocolDecl *Def = cast<ObjCProtocolDecl>(D)->getDefinition())\r
- return MakeCXCursor(Def, TU);\r
- return clang_getNullCursor();\r
-\r
- case Decl::ObjCInterface: {\r
- // There are two notions of a "definition" for an Objective-C\r
- // class: the interface and its implementation. When we resolved a\r
- // reference to an Objective-C class, produce the @interface as\r
- // the definition; when we were provided with the interface,\r
- // produce the @implementation as the definition.\r
- ObjCInterfaceDecl *IFace = cast<ObjCInterfaceDecl>(D);\r
- if (WasReference) {\r
- if (ObjCInterfaceDecl *Def = IFace->getDefinition())\r
- return MakeCXCursor(Def, TU);\r
- } else if (ObjCImplementationDecl *Impl = IFace->getImplementation())\r
- return MakeCXCursor(Impl, TU);\r
- return clang_getNullCursor();\r
- }\r
-\r
- case Decl::ObjCProperty:\r
- // FIXME: We don't really know where to find the\r
- // ObjCPropertyImplDecls that implement this property.\r
- return clang_getNullCursor();\r
-\r
- case Decl::ObjCCompatibleAlias:\r
- if (ObjCInterfaceDecl *Class\r
- = cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())\r
- if (ObjCInterfaceDecl *Def = Class->getDefinition())\r
- return MakeCXCursor(Def, TU);\r
-\r
- return clang_getNullCursor();\r
-\r
- case Decl::Friend:\r
- if (NamedDecl *Friend = cast<FriendDecl>(D)->getFriendDecl())\r
- return clang_getCursorDefinition(MakeCXCursor(Friend, TU));\r
- return clang_getNullCursor();\r
-\r
- case Decl::FriendTemplate:\r
- if (NamedDecl *Friend = cast<FriendTemplateDecl>(D)->getFriendDecl())\r
- return clang_getCursorDefinition(MakeCXCursor(Friend, TU));\r
- return clang_getNullCursor();\r
- }\r
-\r
- return clang_getNullCursor();\r
-}\r
-\r
-unsigned clang_isCursorDefinition(CXCursor C) {\r
- if (!clang_isDeclaration(C.kind))\r
- return 0;\r
-\r
- return clang_getCursorDefinition(C) == C;\r
-}\r
-\r
-CXCursor clang_getCanonicalCursor(CXCursor C) {\r
- if (!clang_isDeclaration(C.kind))\r
- return C;\r
- \r
- if (Decl *D = getCursorDecl(C)) {\r
- if (ObjCCategoryImplDecl *CatImplD = dyn_cast<ObjCCategoryImplDecl>(D))\r
- if (ObjCCategoryDecl *CatD = CatImplD->getCategoryDecl())\r
- return MakeCXCursor(CatD, getCursorTU(C));\r
-\r
- if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D))\r
- if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())\r
- return MakeCXCursor(IFD, getCursorTU(C));\r
-\r
- return MakeCXCursor(D->getCanonicalDecl(), getCursorTU(C));\r
- }\r
- \r
- return C;\r
-}\r
-\r
-int clang_Cursor_getObjCSelectorIndex(CXCursor cursor) {\r
- return cxcursor::getSelectorIdentifierIndexAndLoc(cursor).first;\r
-}\r
- \r
-unsigned clang_getNumOverloadedDecls(CXCursor C) {\r
- if (C.kind != CXCursor_OverloadedDeclRef)\r
- return 0;\r
- \r
- OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;\r
- if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>())\r
- return E->getNumDecls();\r
- \r
- if (OverloadedTemplateStorage *S\r
- = Storage.dyn_cast<OverloadedTemplateStorage*>())\r
- return S->size();\r
- \r
- Decl *D = Storage.get<Decl*>();\r
- if (UsingDecl *Using = dyn_cast<UsingDecl>(D))\r
- return Using->shadow_size();\r
- \r
- return 0;\r
-}\r
-\r
-CXCursor clang_getOverloadedDecl(CXCursor cursor, unsigned index) {\r
- if (cursor.kind != CXCursor_OverloadedDeclRef)\r
- return clang_getNullCursor();\r
-\r
- if (index >= clang_getNumOverloadedDecls(cursor))\r
- return clang_getNullCursor();\r
- \r
- CXTranslationUnit TU = getCursorTU(cursor);\r
- OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(cursor).first;\r
- if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>())\r
- return MakeCXCursor(E->decls_begin()[index], TU);\r
- \r
- if (OverloadedTemplateStorage *S\r
- = Storage.dyn_cast<OverloadedTemplateStorage*>())\r
- return MakeCXCursor(S->begin()[index], TU);\r
- \r
- Decl *D = Storage.get<Decl*>();\r
- if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) {\r
- // FIXME: This is, unfortunately, linear time.\r
- UsingDecl::shadow_iterator Pos = Using->shadow_begin();\r
- std::advance(Pos, index);\r
- return MakeCXCursor(cast<UsingShadowDecl>(*Pos)->getTargetDecl(), TU);\r
- }\r
- \r
- return clang_getNullCursor();\r
-}\r
- \r
-void clang_getDefinitionSpellingAndExtent(CXCursor C,\r
- const char **startBuf,\r
- const char **endBuf,\r
- unsigned *startLine,\r
- unsigned *startColumn,\r
- unsigned *endLine,\r
- unsigned *endColumn) {\r
- assert(getCursorDecl(C) && "CXCursor has null decl");\r
- NamedDecl *ND = static_cast<NamedDecl *>(getCursorDecl(C));\r
- FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);\r
- CompoundStmt *Body = dyn_cast<CompoundStmt>(FD->getBody());\r
-\r
- SourceManager &SM = FD->getASTContext().getSourceManager();\r
- *startBuf = SM.getCharacterData(Body->getLBracLoc());\r
- *endBuf = SM.getCharacterData(Body->getRBracLoc());\r
- *startLine = SM.getSpellingLineNumber(Body->getLBracLoc());\r
- *startColumn = SM.getSpellingColumnNumber(Body->getLBracLoc());\r
- *endLine = SM.getSpellingLineNumber(Body->getRBracLoc());\r
- *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());\r
-}\r
-\r
-\r
-CXSourceRange clang_getCursorReferenceNameRange(CXCursor C, unsigned NameFlags,\r
- unsigned PieceIndex) {\r
- RefNamePieces Pieces;\r
- \r
- switch (C.kind) {\r
- case CXCursor_MemberRefExpr:\r
- if (MemberExpr *E = dyn_cast<MemberExpr>(getCursorExpr(C)))\r
- Pieces = buildPieces(NameFlags, true, E->getMemberNameInfo(),\r
- E->getQualifierLoc().getSourceRange());\r
- break;\r
- \r
- case CXCursor_DeclRefExpr:\r
- if (DeclRefExpr *E = dyn_cast<DeclRefExpr>(getCursorExpr(C)))\r
- Pieces = buildPieces(NameFlags, false, E->getNameInfo(), \r
- E->getQualifierLoc().getSourceRange(),\r
- E->getOptionalExplicitTemplateArgs());\r
- break;\r
- \r
- case CXCursor_CallExpr:\r
- if (CXXOperatorCallExpr *OCE = \r
- dyn_cast<CXXOperatorCallExpr>(getCursorExpr(C))) {\r
- Expr *Callee = OCE->getCallee();\r
- if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Callee))\r
- Callee = ICE->getSubExpr();\r
-\r
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee))\r
- Pieces = buildPieces(NameFlags, false, DRE->getNameInfo(),\r
- DRE->getQualifierLoc().getSourceRange());\r
- }\r
- break;\r
- \r
- default:\r
- break;\r
- }\r
-\r
- if (Pieces.empty()) {\r
- if (PieceIndex == 0)\r
- return clang_getCursorExtent(C);\r
- } else if (PieceIndex < Pieces.size()) {\r
- SourceRange R = Pieces[PieceIndex];\r
- if (R.isValid())\r
- return cxloc::translateSourceRange(getCursorContext(C), R);\r
- }\r
- \r
- return clang_getNullRange();\r
-}\r
-\r
-void clang_enableStackTraces(void) {\r
- llvm::sys::PrintStackTraceOnErrorSignal();\r
-}\r
-\r
-void clang_executeOnThread(void (*fn)(void*), void *user_data,\r
- unsigned stack_size) {\r
- llvm::llvm_execute_on_thread(fn, user_data, stack_size);\r
-}\r
-\r
-} // end: extern "C"\r
-\r
-//===----------------------------------------------------------------------===//\r
-// Token-based Operations.\r
-//===----------------------------------------------------------------------===//\r
-\r
-/* CXToken layout:\r
- * int_data[0]: a CXTokenKind\r
- * int_data[1]: starting token location\r
- * int_data[2]: token length\r
- * int_data[3]: reserved\r
- * ptr_data: for identifiers and keywords, an IdentifierInfo*.\r
- * otherwise unused.\r
- */\r
-extern "C" {\r
-\r
-CXTokenKind clang_getTokenKind(CXToken CXTok) {\r
- return static_cast<CXTokenKind>(CXTok.int_data[0]);\r
-}\r
-\r
-CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) {\r
- switch (clang_getTokenKind(CXTok)) {\r
- case CXToken_Identifier:\r
- case CXToken_Keyword:\r
- // We know we have an IdentifierInfo*, so use that.\r
- return createCXString(static_cast<IdentifierInfo *>(CXTok.ptr_data)\r
- ->getNameStart());\r
-\r
- case CXToken_Literal: {\r
- // We have stashed the starting pointer in the ptr_data field. Use it.\r
- const char *Text = static_cast<const char *>(CXTok.ptr_data);\r
- return createCXString(StringRef(Text, CXTok.int_data[2]));\r
- }\r
-\r
- case CXToken_Punctuation:\r
- case CXToken_Comment:\r
- break;\r
- }\r
-\r
- // We have to find the starting buffer pointer the hard way, by\r
- // deconstructing the source location.\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);\r
- if (!CXXUnit)\r
- return createCXString("");\r
-\r
- SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]);\r
- std::pair<FileID, unsigned> LocInfo\r
- = CXXUnit->getSourceManager().getDecomposedSpellingLoc(Loc);\r
- bool Invalid = false;\r
- StringRef Buffer\r
- = CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid);\r
- if (Invalid)\r
- return createCXString("");\r
-\r
- return createCXString(Buffer.substr(LocInfo.second, CXTok.int_data[2]));\r
-}\r
-\r
-CXSourceLocation clang_getTokenLocation(CXTranslationUnit TU, CXToken CXTok) {\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);\r
- if (!CXXUnit)\r
- return clang_getNullLocation();\r
-\r
- return cxloc::translateSourceLocation(CXXUnit->getASTContext(),\r
- SourceLocation::getFromRawEncoding(CXTok.int_data[1]));\r
-}\r
-\r
-CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) {\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);\r
- if (!CXXUnit)\r
- return clang_getNullRange();\r
-\r
- return cxloc::translateSourceRange(CXXUnit->getASTContext(),\r
- SourceLocation::getFromRawEncoding(CXTok.int_data[1]));\r
-}\r
-\r
-static void getTokens(ASTUnit *CXXUnit, SourceRange Range,\r
- SmallVectorImpl<CXToken> &CXTokens) {\r
- SourceManager &SourceMgr = CXXUnit->getSourceManager();\r
- std::pair<FileID, unsigned> BeginLocInfo\r
- = SourceMgr.getDecomposedLoc(Range.getBegin());\r
- std::pair<FileID, unsigned> EndLocInfo\r
- = SourceMgr.getDecomposedLoc(Range.getEnd());\r
-\r
- // Cannot tokenize across files.\r
- if (BeginLocInfo.first != EndLocInfo.first)\r
- return;\r
-\r
- // Create a lexer\r
- bool Invalid = false;\r
- StringRef Buffer\r
- = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid);\r
- if (Invalid)\r
- return;\r
- \r
- Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),\r
- CXXUnit->getASTContext().getLangOpts(),\r
- Buffer.begin(), Buffer.data() + BeginLocInfo.second, Buffer.end());\r
- Lex.SetCommentRetentionState(true);\r
-\r
- // Lex tokens until we hit the end of the range.\r
- const char *EffectiveBufferEnd = Buffer.data() + EndLocInfo.second;\r
- Token Tok;\r
- bool previousWasAt = false;\r
- do {\r
- // Lex the next token\r
- Lex.LexFromRawLexer(Tok);\r
- if (Tok.is(tok::eof))\r
- break;\r
-\r
- // Initialize the CXToken.\r
- CXToken CXTok;\r
-\r
- // - Common fields\r
- CXTok.int_data[1] = Tok.getLocation().getRawEncoding();\r
- CXTok.int_data[2] = Tok.getLength();\r
- CXTok.int_data[3] = 0;\r
-\r
- // - Kind-specific fields\r
- if (Tok.isLiteral()) {\r
- CXTok.int_data[0] = CXToken_Literal;\r
- CXTok.ptr_data = (void *)Tok.getLiteralData();\r
- } else if (Tok.is(tok::raw_identifier)) {\r
- // Lookup the identifier to determine whether we have a keyword.\r
- IdentifierInfo *II\r
- = CXXUnit->getPreprocessor().LookUpIdentifierInfo(Tok);\r
-\r
- if ((II->getObjCKeywordID() != tok::objc_not_keyword) && previousWasAt) {\r
- CXTok.int_data[0] = CXToken_Keyword;\r
- }\r
- else {\r
- CXTok.int_data[0] = Tok.is(tok::identifier)\r
- ? CXToken_Identifier\r
- : CXToken_Keyword;\r
- }\r
- CXTok.ptr_data = II;\r
- } else if (Tok.is(tok::comment)) {\r
- CXTok.int_data[0] = CXToken_Comment;\r
- CXTok.ptr_data = 0;\r
- } else {\r
- CXTok.int_data[0] = CXToken_Punctuation;\r
- CXTok.ptr_data = 0;\r
- }\r
- CXTokens.push_back(CXTok);\r
- previousWasAt = Tok.is(tok::at);\r
- } while (Lex.getBufferLocation() <= EffectiveBufferEnd);\r
-}\r
-\r
-void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,\r
- CXToken **Tokens, unsigned *NumTokens) {\r
- if (Tokens)\r
- *Tokens = 0;\r
- if (NumTokens)\r
- *NumTokens = 0;\r
-\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);\r
- if (!CXXUnit || !Tokens || !NumTokens)\r
- return;\r
-\r
- ASTUnit::ConcurrencyCheck Check(*CXXUnit);\r
- \r
- SourceRange R = cxloc::translateCXSourceRange(Range);\r
- if (R.isInvalid())\r
- return;\r
-\r
- SmallVector<CXToken, 32> CXTokens;\r
- getTokens(CXXUnit, R, CXTokens);\r
-\r
- if (CXTokens.empty())\r
- return;\r
-\r
- *Tokens = (CXToken *)malloc(sizeof(CXToken) * CXTokens.size());\r
- memmove(*Tokens, CXTokens.data(), sizeof(CXToken) * CXTokens.size());\r
- *NumTokens = CXTokens.size();\r
-}\r
-\r
-void clang_disposeTokens(CXTranslationUnit TU,\r
- CXToken *Tokens, unsigned NumTokens) {\r
- free(Tokens);\r
-}\r
-\r
-} // end: extern "C"\r
-\r
-//===----------------------------------------------------------------------===//\r
-// Token annotation APIs.\r
-//===----------------------------------------------------------------------===//\r
-\r
-typedef llvm::DenseMap<unsigned, CXCursor> AnnotateTokensData;\r
-static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,\r
- CXCursor parent,\r
- CXClientData client_data);\r
-static bool AnnotateTokensPostChildrenVisitor(CXCursor cursor,\r
- CXClientData client_data);\r
-\r
-namespace {\r
-class AnnotateTokensWorker {\r
- AnnotateTokensData &Annotated;\r
- CXToken *Tokens;\r
- CXCursor *Cursors;\r
- unsigned NumTokens;\r
- unsigned TokIdx;\r
- unsigned PreprocessingTokIdx;\r
- CursorVisitor AnnotateVis;\r
- SourceManager &SrcMgr;\r
- bool HasContextSensitiveKeywords;\r
-\r
- struct PostChildrenInfo {\r
- CXCursor Cursor;\r
- SourceRange CursorRange;\r
- unsigned BeforeChildrenTokenIdx;\r
- };\r
- llvm::SmallVector<PostChildrenInfo, 8> PostChildrenInfos;\r
- \r
- bool MoreTokens() const { return TokIdx < NumTokens; }\r
- unsigned NextToken() const { return TokIdx; }\r
- void AdvanceToken() { ++TokIdx; }\r
- SourceLocation GetTokenLoc(unsigned tokI) {\r
- return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[1]);\r
- }\r
- bool isFunctionMacroToken(unsigned tokI) const {\r
- return Tokens[tokI].int_data[3] != 0;\r
- }\r
- SourceLocation getFunctionMacroTokenLoc(unsigned tokI) const {\r
- return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[3]);\r
- }\r
-\r
- void annotateAndAdvanceTokens(CXCursor, RangeComparisonResult, SourceRange);\r
- void annotateAndAdvanceFunctionMacroTokens(CXCursor, RangeComparisonResult,\r
- SourceRange);\r
-\r
-public:\r
- AnnotateTokensWorker(AnnotateTokensData &annotated,\r
- CXToken *tokens, CXCursor *cursors, unsigned numTokens,\r
- CXTranslationUnit tu, SourceRange RegionOfInterest)\r
- : Annotated(annotated), Tokens(tokens), Cursors(cursors),\r
- NumTokens(numTokens), TokIdx(0), PreprocessingTokIdx(0),\r
- AnnotateVis(tu,\r
- AnnotateTokensVisitor, this,\r
- /*VisitPreprocessorLast=*/true,\r
- /*VisitIncludedEntities=*/false,\r
- RegionOfInterest,\r
- /*VisitDeclsOnly=*/false,\r
- AnnotateTokensPostChildrenVisitor),\r
- SrcMgr(static_cast<ASTUnit*>(tu->TUData)->getSourceManager()),\r
- HasContextSensitiveKeywords(false) { }\r
-\r
- void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); }\r
- enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent);\r
- bool postVisitChildren(CXCursor cursor);\r
- void AnnotateTokens();\r
- \r
- /// \brief Determine whether the annotator saw any cursors that have \r
- /// context-sensitive keywords.\r
- bool hasContextSensitiveKeywords() const {\r
- return HasContextSensitiveKeywords;\r
- }\r
-\r
- ~AnnotateTokensWorker() {\r
- assert(PostChildrenInfos.empty());\r
- }\r
-};\r
-}\r
-\r
-void AnnotateTokensWorker::AnnotateTokens() {\r
- // Walk the AST within the region of interest, annotating tokens\r
- // along the way.\r
- AnnotateVis.visitFileRegion();\r
-\r
- for (unsigned I = 0 ; I < TokIdx ; ++I) {\r
- AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]);\r
- if (Pos != Annotated.end() && !clang_isPreprocessing(Cursors[I].kind))\r
- Cursors[I] = Pos->second;\r
- }\r
-\r
- // Finish up annotating any tokens left.\r
- if (!MoreTokens())\r
- return;\r
-\r
- const CXCursor &C = clang_getNullCursor();\r
- for (unsigned I = TokIdx ; I < NumTokens ; ++I) {\r
- if (I < PreprocessingTokIdx && clang_isPreprocessing(Cursors[I].kind))\r
- continue;\r
-\r
- AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]);\r
- Cursors[I] = (Pos == Annotated.end()) ? C : Pos->second;\r
- }\r
-}\r
-\r
-/// \brief It annotates and advances tokens with a cursor until the comparison\r
-//// between the cursor location and the source range is the same as\r
-/// \arg compResult.\r
-///\r
-/// Pass RangeBefore to annotate tokens with a cursor until a range is reached.\r
-/// Pass RangeOverlap to annotate tokens inside a range.\r
-void AnnotateTokensWorker::annotateAndAdvanceTokens(CXCursor updateC,\r
- RangeComparisonResult compResult,\r
- SourceRange range) {\r
- while (MoreTokens()) {\r
- const unsigned I = NextToken();\r
- if (isFunctionMacroToken(I))\r
- return annotateAndAdvanceFunctionMacroTokens(updateC, compResult, range);\r
-\r
- SourceLocation TokLoc = GetTokenLoc(I);\r
- if (LocationCompare(SrcMgr, TokLoc, range) == compResult) {\r
- Cursors[I] = updateC;\r
- AdvanceToken();\r
- continue;\r
- }\r
- break;\r
- }\r
-}\r
-\r
-/// \brief Special annotation handling for macro argument tokens.\r
-void AnnotateTokensWorker::annotateAndAdvanceFunctionMacroTokens(\r
- CXCursor updateC,\r
- RangeComparisonResult compResult,\r
- SourceRange range) {\r
- assert(MoreTokens());\r
- assert(isFunctionMacroToken(NextToken()) &&\r
- "Should be called only for macro arg tokens");\r
-\r
- // This works differently than annotateAndAdvanceTokens; because expanded\r
- // macro arguments can have arbitrary translation-unit source order, we do not\r
- // advance the token index one by one until a token fails the range test.\r
- // We only advance once past all of the macro arg tokens if all of them\r
- // pass the range test. If one of them fails we keep the token index pointing\r
- // at the start of the macro arg tokens so that the failing token will be\r
- // annotated by a subsequent annotation try.\r
-\r
- bool atLeastOneCompFail = false;\r
- \r
- unsigned I = NextToken();\r
- for (; I < NumTokens && isFunctionMacroToken(I); ++I) {\r
- SourceLocation TokLoc = getFunctionMacroTokenLoc(I);\r
- if (TokLoc.isFileID())\r
- continue; // not macro arg token, it's parens or comma.\r
- if (LocationCompare(SrcMgr, TokLoc, range) == compResult) {\r
- if (clang_isInvalid(clang_getCursorKind(Cursors[I])))\r
- Cursors[I] = updateC;\r
- } else\r
- atLeastOneCompFail = true;\r
- }\r
-\r
- if (!atLeastOneCompFail)\r
- TokIdx = I; // All of the tokens were handled, advance beyond all of them.\r
-}\r
-\r
-enum CXChildVisitResult\r
-AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { \r
- CXSourceLocation Loc = clang_getCursorLocation(cursor);\r
- SourceRange cursorRange = getRawCursorExtent(cursor);\r
- if (cursorRange.isInvalid())\r
- return CXChildVisit_Recurse;\r
- \r
- if (!HasContextSensitiveKeywords) {\r
- // Objective-C properties can have context-sensitive keywords.\r
- if (cursor.kind == CXCursor_ObjCPropertyDecl) {\r
- if (ObjCPropertyDecl *Property \r
- = dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(cursor)))\r
- HasContextSensitiveKeywords = Property->getPropertyAttributesAsWritten() != 0;\r
- }\r
- // Objective-C methods can have context-sensitive keywords.\r
- else if (cursor.kind == CXCursor_ObjCInstanceMethodDecl ||\r
- cursor.kind == CXCursor_ObjCClassMethodDecl) {\r
- if (ObjCMethodDecl *Method\r
- = dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {\r
- if (Method->getObjCDeclQualifier())\r
- HasContextSensitiveKeywords = true;\r
- else {\r
- for (ObjCMethodDecl::param_iterator P = Method->param_begin(),\r
- PEnd = Method->param_end();\r
- P != PEnd; ++P) {\r
- if ((*P)->getObjCDeclQualifier()) {\r
- HasContextSensitiveKeywords = true;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- } \r
- // C++ methods can have context-sensitive keywords.\r
- else if (cursor.kind == CXCursor_CXXMethod) {\r
- if (CXXMethodDecl *Method\r
- = dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(cursor))) {\r
- if (Method->hasAttr<FinalAttr>() || Method->hasAttr<OverrideAttr>())\r
- HasContextSensitiveKeywords = true;\r
- }\r
- }\r
- // C++ classes can have context-sensitive keywords.\r
- else if (cursor.kind == CXCursor_StructDecl ||\r
- cursor.kind == CXCursor_ClassDecl ||\r
- cursor.kind == CXCursor_ClassTemplate ||\r
- cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {\r
- if (Decl *D = getCursorDecl(cursor))\r
- if (D->hasAttr<FinalAttr>())\r
- HasContextSensitiveKeywords = true;\r
- }\r
- }\r
- \r
- if (clang_isPreprocessing(cursor.kind)) { \r
- // Items in the preprocessing record are kept separate from items in\r
- // declarations, so we keep a separate token index.\r
- unsigned SavedTokIdx = TokIdx;\r
- TokIdx = PreprocessingTokIdx;\r
-\r
- // Skip tokens up until we catch up to the beginning of the preprocessing\r
- // entry.\r
- while (MoreTokens()) {\r
- const unsigned I = NextToken();\r
- SourceLocation TokLoc = GetTokenLoc(I);\r
- switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {\r
- case RangeBefore:\r
- AdvanceToken();\r
- continue;\r
- case RangeAfter:\r
- case RangeOverlap:\r
- break;\r
- }\r
- break;\r
- }\r
- \r
- // Look at all of the tokens within this range.\r
- while (MoreTokens()) {\r
- const unsigned I = NextToken();\r
- SourceLocation TokLoc = GetTokenLoc(I);\r
- switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {\r
- case RangeBefore:\r
- llvm_unreachable("Infeasible");\r
- case RangeAfter:\r
- break;\r
- case RangeOverlap:\r
- Cursors[I] = cursor;\r
- AdvanceToken();\r
- // For macro expansions, just note where the beginning of the macro\r
- // expansion occurs.\r
- if (cursor.kind == CXCursor_MacroExpansion)\r
- break;\r
- continue;\r
- }\r
- break;\r
- }\r
-\r
- // Save the preprocessing token index; restore the non-preprocessing\r
- // token index.\r
- PreprocessingTokIdx = TokIdx;\r
- TokIdx = SavedTokIdx;\r
- return CXChildVisit_Recurse;\r
- }\r
-\r
- if (cursorRange.isInvalid())\r
- return CXChildVisit_Continue;\r
- \r
- SourceLocation L = SourceLocation::getFromRawEncoding(Loc.int_data);\r
-\r
- // Adjust the annotated range based specific declarations.\r
- const enum CXCursorKind cursorK = clang_getCursorKind(cursor);\r
- if (clang_isDeclaration(cursorK)) {\r
- Decl *D = cxcursor::getCursorDecl(cursor);\r
- \r
- SourceLocation StartLoc;\r
- if (const DeclaratorDecl *DD = dyn_cast_or_null<DeclaratorDecl>(D)) {\r
- if (TypeSourceInfo *TI = DD->getTypeSourceInfo())\r
- StartLoc = TI->getTypeLoc().getLocStart();\r
- } else if (TypedefDecl *Typedef = dyn_cast_or_null<TypedefDecl>(D)) {\r
- if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())\r
- StartLoc = TI->getTypeLoc().getLocStart();\r
- }\r
-\r
- if (StartLoc.isValid() && L.isValid() &&\r
- SrcMgr.isBeforeInTranslationUnit(StartLoc, L))\r
- cursorRange.setBegin(StartLoc);\r
- }\r
- \r
- // If the location of the cursor occurs within a macro instantiation, record\r
- // the spelling location of the cursor in our annotation map. We can then\r
- // paper over the token labelings during a post-processing step to try and\r
- // get cursor mappings for tokens that are the *arguments* of a macro\r
- // instantiation.\r
- if (L.isMacroID()) {\r
- unsigned rawEncoding = SrcMgr.getSpellingLoc(L).getRawEncoding();\r
- // Only invalidate the old annotation if it isn't part of a preprocessing\r
- // directive. Here we assume that the default construction of CXCursor\r
- // results in CXCursor.kind being an initialized value (i.e., 0). If\r
- // this isn't the case, we can fix by doing lookup + insertion.\r
- \r
- CXCursor &oldC = Annotated[rawEncoding];\r
- if (!clang_isPreprocessing(oldC.kind))\r
- oldC = cursor;\r
- }\r
- \r
- const enum CXCursorKind K = clang_getCursorKind(parent);\r
- const CXCursor updateC =\r
- (clang_isInvalid(K) || K == CXCursor_TranslationUnit)\r
- ? clang_getNullCursor() : parent;\r
-\r
- annotateAndAdvanceTokens(updateC, RangeBefore, cursorRange);\r
-\r
- // Avoid having the cursor of an expression "overwrite" the annotation of the\r
- // variable declaration that it belongs to.\r
- // This can happen for C++ constructor expressions whose range generally\r
- // include the variable declaration, e.g.:\r
- // MyCXXClass foo; // Make sure we don't annotate 'foo' as a CallExpr cursor.\r
- if (clang_isExpression(cursorK)) {\r
- Expr *E = getCursorExpr(cursor);\r
- if (Decl *D = getCursorParentDecl(cursor)) {\r
- const unsigned I = NextToken();\r
- if (E->getLocStart().isValid() && D->getLocation().isValid() &&\r
- E->getLocStart() == D->getLocation() &&\r
- E->getLocStart() == GetTokenLoc(I)) {\r
- Cursors[I] = updateC;\r
- AdvanceToken();\r
- }\r
- }\r
- }\r
-\r
- // Before recursing into the children keep some state that we are going\r
- // to use in the AnnotateTokensWorker::postVisitChildren callback to do some\r
- // extra work after the child nodes are visited.\r
- // Note that we don't call VisitChildren here to avoid traversing statements\r
- // code-recursively which can blow the stack.\r
-\r
- PostChildrenInfo Info;\r
- Info.Cursor = cursor;\r
- Info.CursorRange = cursorRange;\r
- Info.BeforeChildrenTokenIdx = NextToken();\r
- PostChildrenInfos.push_back(Info);\r
-\r
- return CXChildVisit_Recurse;\r
-}\r
-\r
-bool AnnotateTokensWorker::postVisitChildren(CXCursor cursor) {\r
- if (PostChildrenInfos.empty())\r
- return false;\r
- const PostChildrenInfo &Info = PostChildrenInfos.back();\r
- if (!clang_equalCursors(Info.Cursor, cursor))\r
- return false;\r
-\r
- const unsigned BeforeChildren = Info.BeforeChildrenTokenIdx;\r
- const unsigned AfterChildren = NextToken();\r
- SourceRange cursorRange = Info.CursorRange;\r
-\r
- // Scan the tokens that are at the end of the cursor, but are not captured\r
- // but the child cursors.\r
- annotateAndAdvanceTokens(cursor, RangeOverlap, cursorRange);\r
-\r
- // Scan the tokens that are at the beginning of the cursor, but are not\r
- // capture by the child cursors.\r
- for (unsigned I = BeforeChildren; I != AfterChildren; ++I) {\r
- if (!clang_isInvalid(clang_getCursorKind(Cursors[I])))\r
- break;\r
-\r
- Cursors[I] = cursor;\r
- }\r
-\r
- PostChildrenInfos.pop_back();\r
- return false;\r
-}\r
-\r
-static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,\r
- CXCursor parent,\r
- CXClientData client_data) {\r
- return static_cast<AnnotateTokensWorker*>(client_data)->Visit(cursor, parent);\r
-}\r
-\r
-static bool AnnotateTokensPostChildrenVisitor(CXCursor cursor,\r
- CXClientData client_data) {\r
- return static_cast<AnnotateTokensWorker*>(client_data)->\r
- postVisitChildren(cursor);\r
-}\r
-\r
-namespace {\r
-\r
-/// \brief Uses the macro expansions in the preprocessing record to find\r
-/// and mark tokens that are macro arguments. This info is used by the\r
-/// AnnotateTokensWorker.\r
-class MarkMacroArgTokensVisitor {\r
- SourceManager &SM;\r
- CXToken *Tokens;\r
- unsigned NumTokens;\r
- unsigned CurIdx;\r
- \r
-public:\r
- MarkMacroArgTokensVisitor(SourceManager &SM,\r
- CXToken *tokens, unsigned numTokens)\r
- : SM(SM), Tokens(tokens), NumTokens(numTokens), CurIdx(0) { }\r
-\r
- CXChildVisitResult visit(CXCursor cursor, CXCursor parent) {\r
- if (cursor.kind != CXCursor_MacroExpansion)\r
- return CXChildVisit_Continue;\r
-\r
- SourceRange macroRange = getCursorMacroExpansion(cursor)->getSourceRange();\r
- if (macroRange.getBegin() == macroRange.getEnd())\r
- return CXChildVisit_Continue; // it's not a function macro.\r
-\r
- for (; CurIdx < NumTokens; ++CurIdx) {\r
- if (!SM.isBeforeInTranslationUnit(getTokenLoc(CurIdx),\r
- macroRange.getBegin()))\r
- break;\r
- }\r
- \r
- if (CurIdx == NumTokens)\r
- return CXChildVisit_Break;\r
-\r
- for (; CurIdx < NumTokens; ++CurIdx) {\r
- SourceLocation tokLoc = getTokenLoc(CurIdx);\r
- if (!SM.isBeforeInTranslationUnit(tokLoc, macroRange.getEnd()))\r
- break;\r
-\r
- setFunctionMacroTokenLoc(CurIdx, SM.getMacroArgExpandedLocation(tokLoc));\r
- }\r
-\r
- if (CurIdx == NumTokens)\r
- return CXChildVisit_Break;\r
-\r
- return CXChildVisit_Continue;\r
- }\r
-\r
-private:\r
- SourceLocation getTokenLoc(unsigned tokI) {\r
- return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[1]);\r
- }\r
-\r
- void setFunctionMacroTokenLoc(unsigned tokI, SourceLocation loc) {\r
- // The third field is reserved and currently not used. Use it here\r
- // to mark macro arg expanded tokens with their expanded locations.\r
- Tokens[tokI].int_data[3] = loc.getRawEncoding();\r
- }\r
-};\r
-\r
-} // end anonymous namespace\r
-\r
-static CXChildVisitResult\r
-MarkMacroArgTokensVisitorDelegate(CXCursor cursor, CXCursor parent,\r
- CXClientData client_data) {\r
- return static_cast<MarkMacroArgTokensVisitor*>(client_data)->visit(cursor,\r
- parent);\r
-}\r
-\r
-namespace {\r
- struct clang_annotateTokens_Data {\r
- CXTranslationUnit TU;\r
- ASTUnit *CXXUnit;\r
- CXToken *Tokens;\r
- unsigned NumTokens;\r
- CXCursor *Cursors;\r
- };\r
-}\r
-\r
-static void annotatePreprocessorTokens(CXTranslationUnit TU,\r
- SourceRange RegionOfInterest,\r
- AnnotateTokensData &Annotated) {\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);\r
-\r
- SourceManager &SourceMgr = CXXUnit->getSourceManager();\r
- std::pair<FileID, unsigned> BeginLocInfo\r
- = SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin());\r
- std::pair<FileID, unsigned> EndLocInfo\r
- = SourceMgr.getDecomposedLoc(RegionOfInterest.getEnd());\r
-\r
- if (BeginLocInfo.first != EndLocInfo.first)\r
- return;\r
-\r
- StringRef Buffer;\r
- bool Invalid = false;\r
- Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid);\r
- if (Buffer.empty() || Invalid)\r
- return;\r
-\r
- Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),\r
- CXXUnit->getASTContext().getLangOpts(),\r
- Buffer.begin(), Buffer.data() + BeginLocInfo.second,\r
- Buffer.end());\r
- Lex.SetCommentRetentionState(true);\r
- \r
- // Lex tokens in raw mode until we hit the end of the range, to avoid\r
- // entering #includes or expanding macros.\r
- while (true) {\r
- Token Tok;\r
- Lex.LexFromRawLexer(Tok);\r
- \r
- reprocess:\r
- if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {\r
- // We have found a preprocessing directive. Gobble it up so that we\r
- // don't see it while preprocessing these tokens later, but keep track\r
- // of all of the token locations inside this preprocessing directive so\r
- // that we can annotate them appropriately.\r
- //\r
- // FIXME: Some simple tests here could identify macro definitions and\r
- // #undefs, to provide specific cursor kinds for those.\r
- SmallVector<SourceLocation, 32> Locations;\r
- do {\r
- Locations.push_back(Tok.getLocation());\r
- Lex.LexFromRawLexer(Tok);\r
- } while (!Tok.isAtStartOfLine() && !Tok.is(tok::eof));\r
- \r
- using namespace cxcursor;\r
- CXCursor Cursor\r
- = MakePreprocessingDirectiveCursor(SourceRange(Locations.front(),\r
- Locations.back()),\r
- TU);\r
- for (unsigned I = 0, N = Locations.size(); I != N; ++I) {\r
- Annotated[Locations[I].getRawEncoding()] = Cursor;\r
- }\r
- \r
- if (Tok.isAtStartOfLine())\r
- goto reprocess;\r
- \r
- continue;\r
- }\r
- \r
- if (Tok.is(tok::eof))\r
- break;\r
- }\r
-}\r
-\r
-// This gets run a separate thread to avoid stack blowout.\r
-static void clang_annotateTokensImpl(void *UserData) {\r
- CXTranslationUnit TU = ((clang_annotateTokens_Data*)UserData)->TU;\r
- ASTUnit *CXXUnit = ((clang_annotateTokens_Data*)UserData)->CXXUnit;\r
- CXToken *Tokens = ((clang_annotateTokens_Data*)UserData)->Tokens;\r
- const unsigned NumTokens = ((clang_annotateTokens_Data*)UserData)->NumTokens;\r
- CXCursor *Cursors = ((clang_annotateTokens_Data*)UserData)->Cursors;\r
-\r
- CIndexer *CXXIdx = (CIndexer*)TU->CIdx;\r
- if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))\r
- setThreadBackgroundPriority();\r
-\r
- // Determine the region of interest, which contains all of the tokens.\r
- SourceRange RegionOfInterest;\r
- RegionOfInterest.setBegin(\r
- cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0])));\r
- RegionOfInterest.setEnd(\r
- cxloc::translateSourceLocation(clang_getTokenLocation(TU,\r
- Tokens[NumTokens-1])));\r
-\r
- // A mapping from the source locations found when re-lexing or traversing the\r
- // region of interest to the corresponding cursors.\r
- AnnotateTokensData Annotated;\r
-\r
- // Relex the tokens within the source range to look for preprocessing\r
- // directives.\r
- annotatePreprocessorTokens(TU, RegionOfInterest, Annotated);\r
- \r
- if (CXXUnit->getPreprocessor().getPreprocessingRecord()) {\r
- // Search and mark tokens that are macro argument expansions.\r
- MarkMacroArgTokensVisitor Visitor(CXXUnit->getSourceManager(),\r
- Tokens, NumTokens);\r
- CursorVisitor MacroArgMarker(TU,\r
- MarkMacroArgTokensVisitorDelegate, &Visitor,\r
- /*VisitPreprocessorLast=*/true,\r
- /*VisitIncludedEntities=*/false,\r
- RegionOfInterest);\r
- MacroArgMarker.visitPreprocessedEntitiesInRegion();\r
- }\r
- \r
- // Annotate all of the source locations in the region of interest that map to\r
- // a specific cursor.\r
- AnnotateTokensWorker W(Annotated, Tokens, Cursors, NumTokens,\r
- TU, RegionOfInterest);\r
- \r
- // FIXME: We use a ridiculous stack size here because the data-recursion\r
- // algorithm uses a large stack frame than the non-data recursive version,\r
- // and AnnotationTokensWorker currently transforms the data-recursion\r
- // algorithm back into a traditional recursion by explicitly calling\r
- // VisitChildren(). We will need to remove this explicit recursive call.\r
- W.AnnotateTokens();\r
-\r
- // If we ran into any entities that involve context-sensitive keywords,\r
- // take another pass through the tokens to mark them as such.\r
- if (W.hasContextSensitiveKeywords()) {\r
- for (unsigned I = 0; I != NumTokens; ++I) {\r
- if (clang_getTokenKind(Tokens[I]) != CXToken_Identifier)\r
- continue;\r
- \r
- if (Cursors[I].kind == CXCursor_ObjCPropertyDecl) {\r
- IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);\r
- if (ObjCPropertyDecl *Property\r
- = dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(Cursors[I]))) {\r
- if (Property->getPropertyAttributesAsWritten() != 0 &&\r
- llvm::StringSwitch<bool>(II->getName())\r
- .Case("readonly", true)\r
- .Case("assign", true)\r
- .Case("unsafe_unretained", true)\r
- .Case("readwrite", true)\r
- .Case("retain", true)\r
- .Case("copy", true)\r
- .Case("nonatomic", true)\r
- .Case("atomic", true)\r
- .Case("getter", true)\r
- .Case("setter", true)\r
- .Case("strong", true)\r
- .Case("weak", true)\r
- .Default(false))\r
- Tokens[I].int_data[0] = CXToken_Keyword;\r
- }\r
- continue;\r
- }\r
- \r
- if (Cursors[I].kind == CXCursor_ObjCInstanceMethodDecl ||\r
- Cursors[I].kind == CXCursor_ObjCClassMethodDecl) {\r
- IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);\r
- if (llvm::StringSwitch<bool>(II->getName())\r
- .Case("in", true)\r
- .Case("out", true)\r
- .Case("inout", true)\r
- .Case("oneway", true)\r
- .Case("bycopy", true)\r
- .Case("byref", true)\r
- .Default(false))\r
- Tokens[I].int_data[0] = CXToken_Keyword;\r
- continue;\r
- }\r
-\r
- if (Cursors[I].kind == CXCursor_CXXFinalAttr ||\r
- Cursors[I].kind == CXCursor_CXXOverrideAttr) {\r
- Tokens[I].int_data[0] = CXToken_Keyword;\r
- continue;\r
- }\r
- }\r
- }\r
-}\r
-\r
-extern "C" {\r
-\r
-void clang_annotateTokens(CXTranslationUnit TU,\r
- CXToken *Tokens, unsigned NumTokens,\r
- CXCursor *Cursors) {\r
-\r
- if (NumTokens == 0 || !Tokens || !Cursors)\r
- return;\r
-\r
- // Any token we don't specifically annotate will have a NULL cursor.\r
- CXCursor C = clang_getNullCursor();\r
- for (unsigned I = 0; I != NumTokens; ++I)\r
- Cursors[I] = C;\r
-\r
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);\r
- if (!CXXUnit)\r
- return;\r
-\r
- ASTUnit::ConcurrencyCheck Check(*CXXUnit);\r
- \r
- clang_annotateTokens_Data data = { TU, CXXUnit, Tokens, NumTokens, Cursors };\r
- llvm::CrashRecoveryContext CRC;\r
- if (!RunSafely(CRC, clang_annotateTokensImpl, &data,\r
- GetSafetyThreadStackSize() * 2)) {\r
- fprintf(stderr, "libclang: crash detected while annotating tokens\n");\r
- }\r
-}\r
-\r
-} // end: extern "C"\r
-\r
-//===----------------------------------------------------------------------===//\r
-// Operations for querying linkage of a cursor.\r
-//===----------------------------------------------------------------------===//\r
-\r
-extern "C" {\r
-CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {\r
- if (!clang_isDeclaration(cursor.kind))\r
- return CXLinkage_Invalid;\r
-\r
- Decl *D = cxcursor::getCursorDecl(cursor);\r
- if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))\r
- switch (ND->getLinkage()) {\r
- case NoLinkage: return CXLinkage_NoLinkage;\r
- case InternalLinkage: return CXLinkage_Internal;\r
- case UniqueExternalLinkage: return CXLinkage_UniqueExternal;\r
- case ExternalLinkage: return CXLinkage_External;\r
- };\r
-\r
- return CXLinkage_Invalid;\r
-}\r
-} // end: extern "C"\r
-\r
-//===----------------------------------------------------------------------===//\r
-// Operations for querying language of a cursor.\r
-//===----------------------------------------------------------------------===//\r
-\r
-static CXLanguageKind getDeclLanguage(const Decl *D) {\r
- if (!D)\r
- return CXLanguage_C;\r
-\r
- switch (D->getKind()) {\r
- default:\r
- break;\r
- case Decl::ImplicitParam:\r
- case Decl::ObjCAtDefsField:\r
- case Decl::ObjCCategory:\r
- case Decl::ObjCCategoryImpl:\r
- case Decl::ObjCCompatibleAlias:\r
- case Decl::ObjCImplementation:\r
- case Decl::ObjCInterface:\r
- case Decl::ObjCIvar:\r
- case Decl::ObjCMethod:\r
- case Decl::ObjCProperty:\r
- case Decl::ObjCPropertyImpl:\r
- case Decl::ObjCProtocol:\r
- return CXLanguage_ObjC;\r
- case Decl::CXXConstructor:\r
- case Decl::CXXConversion:\r
- case Decl::CXXDestructor:\r
- case Decl::CXXMethod:\r
- case Decl::CXXRecord:\r
- case Decl::ClassTemplate:\r
- case Decl::ClassTemplatePartialSpecialization:\r
- case Decl::ClassTemplateSpecialization:\r
- case Decl::Friend:\r
- case Decl::FriendTemplate:\r
- case Decl::FunctionTemplate:\r
- case Decl::LinkageSpec:\r
- case Decl::Namespace:\r
- case Decl::NamespaceAlias:\r
- case Decl::NonTypeTemplateParm:\r
- case Decl::StaticAssert:\r
- case Decl::TemplateTemplateParm:\r
- case Decl::TemplateTypeParm:\r
- case Decl::UnresolvedUsingTypename:\r
- case Decl::UnresolvedUsingValue:\r
- case Decl::Using:\r
- case Decl::UsingDirective:\r
- case Decl::UsingShadow:\r
- return CXLanguage_CPlusPlus;\r
- }\r
-\r
- return CXLanguage_C;\r
-}\r
-\r
-extern "C" {\r
- \r
-enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {\r
- if (clang_isDeclaration(cursor.kind))\r
- if (Decl *D = cxcursor::getCursorDecl(cursor)) {\r
- if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted())\r
- return CXAvailability_Available;\r
- \r
- switch (D->getAvailability()) {\r
- case AR_Available:\r
- case AR_NotYetIntroduced:\r
- return CXAvailability_Available;\r
-\r
- case AR_Deprecated:\r
- return CXAvailability_Deprecated;\r
-\r
- case AR_Unavailable:\r
- return CXAvailability_NotAvailable;\r
- }\r
- }\r
-\r
- return CXAvailability_Available;\r
-}\r
-\r
-static CXVersion convertVersion(VersionTuple In) {\r
- CXVersion Out = { -1, -1, -1 };\r
- if (In.empty())\r
- return Out;\r
-\r
- Out.Major = In.getMajor();\r
- \r
- if (llvm::Optional<unsigned> Minor = In.getMinor())\r
- Out.Minor = *Minor;\r
- else\r
- return Out;\r
-\r
- if (llvm::Optional<unsigned> Subminor = In.getSubminor())\r
- Out.Subminor = *Subminor;\r
- \r
- return Out;\r
-}\r
- \r
-int clang_getCursorPlatformAvailability(CXCursor cursor,\r
- int *always_deprecated,\r
- CXString *deprecated_message,\r
- int *always_unavailable,\r
- CXString *unavailable_message,\r
- CXPlatformAvailability *availability,\r
- int availability_size) {\r
- if (always_deprecated)\r
- *always_deprecated = 0;\r
- if (deprecated_message)\r
- *deprecated_message = cxstring::createCXString("", /*DupString=*/false);\r
- if (always_unavailable)\r
- *always_unavailable = 0;\r
- if (unavailable_message)\r
- *unavailable_message = cxstring::createCXString("", /*DupString=*/false);\r
- \r
- if (!clang_isDeclaration(cursor.kind))\r
- return 0;\r
- \r
- Decl *D = cxcursor::getCursorDecl(cursor);\r
- if (!D)\r
- return 0;\r
- \r
- int N = 0;\r
- for (Decl::attr_iterator A = D->attr_begin(), AEnd = D->attr_end(); A != AEnd;\r
- ++A) {\r
- if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(*A)) {\r
- if (always_deprecated)\r
- *always_deprecated = 1;\r
- if (deprecated_message)\r
- *deprecated_message = cxstring::createCXString(Deprecated->getMessage());\r
- continue;\r
- }\r
- \r
- if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(*A)) {\r
- if (always_unavailable)\r
- *always_unavailable = 1;\r
- if (unavailable_message) {\r
- *unavailable_message\r
- = cxstring::createCXString(Unavailable->getMessage());\r
- }\r
- continue;\r
- }\r
- \r
- if (AvailabilityAttr *Avail = dyn_cast<AvailabilityAttr>(*A)) {\r
- if (N < availability_size) {\r
- availability[N].Platform\r
- = cxstring::createCXString(Avail->getPlatform()->getName());\r
- availability[N].Introduced = convertVersion(Avail->getIntroduced());\r
- availability[N].Deprecated = convertVersion(Avail->getDeprecated());\r
- availability[N].Obsoleted = convertVersion(Avail->getObsoleted());\r
- availability[N].Unavailable = Avail->getUnavailable();\r
- availability[N].Message = cxstring::createCXString(Avail->getMessage());\r
- }\r
- ++N;\r
- }\r
- }\r
- \r
- return N;\r
-}\r
- \r
-void clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability) {\r
- clang_disposeString(availability->Platform);\r
- clang_disposeString(availability->Message);\r
-}\r
-\r
-CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {\r
- if (clang_isDeclaration(cursor.kind))\r
- return getDeclLanguage(cxcursor::getCursorDecl(cursor));\r
-\r
- return CXLanguage_Invalid;\r
-}\r
-\r
- /// \brief If the given cursor is the "templated" declaration\r
- /// descibing a class or function template, return the class or\r
- /// function template.\r
-static Decl *maybeGetTemplateCursor(Decl *D) {\r
- if (!D)\r
- return 0;\r
-\r
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))\r
- if (FunctionTemplateDecl *FunTmpl = FD->getDescribedFunctionTemplate())\r
- return FunTmpl;\r
-\r
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))\r
- if (ClassTemplateDecl *ClassTmpl = RD->getDescribedClassTemplate())\r
- return ClassTmpl;\r
-\r
- return D;\r
-}\r
-\r
-CXCursor clang_getCursorSemanticParent(CXCursor cursor) {\r
- if (clang_isDeclaration(cursor.kind)) {\r
- if (Decl *D = getCursorDecl(cursor)) {\r
- DeclContext *DC = D->getDeclContext();\r
- if (!DC)\r
- return clang_getNullCursor();\r
-\r
- return MakeCXCursor(maybeGetTemplateCursor(cast<Decl>(DC)), \r
- getCursorTU(cursor));\r
- }\r
- }\r
- \r
- if (clang_isStatement(cursor.kind) || clang_isExpression(cursor.kind)) {\r
- if (Decl *D = getCursorDecl(cursor))\r
- return MakeCXCursor(D, getCursorTU(cursor));\r
- }\r
- \r
- return clang_getNullCursor();\r
-}\r
-\r
-CXCursor clang_getCursorLexicalParent(CXCursor cursor) {\r
- if (clang_isDeclaration(cursor.kind)) {\r
- if (Decl *D = getCursorDecl(cursor)) {\r
- DeclContext *DC = D->getLexicalDeclContext();\r
- if (!DC)\r
- return clang_getNullCursor();\r
-\r
- return MakeCXCursor(maybeGetTemplateCursor(cast<Decl>(DC)), \r
- getCursorTU(cursor));\r
- }\r
- }\r
-\r
- // FIXME: Note that we can't easily compute the lexical context of a \r
- // statement or expression, so we return nothing.\r
- return clang_getNullCursor();\r
-}\r
-\r
-CXFile clang_getIncludedFile(CXCursor cursor) {\r
- if (cursor.kind != CXCursor_InclusionDirective)\r
- return 0;\r
- \r
- InclusionDirective *ID = getCursorInclusionDirective(cursor);\r
- return (void *)ID->getFile();\r
-}\r
-\r
-CXSourceRange clang_Cursor_getCommentRange(CXCursor C) {\r
- if (!clang_isDeclaration(C.kind))\r
- return clang_getNullRange();\r
-\r
- const Decl *D = getCursorDecl(C);\r
- ASTContext &Context = getCursorContext(C);\r
- const RawComment *RC = Context.getRawCommentForAnyRedecl(D);\r
- if (!RC)\r
- return clang_getNullRange();\r
-\r
- return cxloc::translateSourceRange(Context, RC->getSourceRange());\r
-}\r
-\r
-CXString clang_Cursor_getRawCommentText(CXCursor C) {\r
- if (!clang_isDeclaration(C.kind))\r
- return createCXString((const char *) NULL);\r
-\r
- const Decl *D = getCursorDecl(C);\r
- ASTContext &Context = getCursorContext(C);\r
- const RawComment *RC = Context.getRawCommentForAnyRedecl(D);\r
- StringRef RawText = RC ? RC->getRawText(Context.getSourceManager()) :\r
- StringRef();\r
-\r
- // Don't duplicate the string because RawText points directly into source\r
- // code.\r
- return createCXString(RawText, false);\r
-}\r
-\r
-CXString clang_Cursor_getBriefCommentText(CXCursor C) {\r
- if (!clang_isDeclaration(C.kind))\r
- return createCXString((const char *) NULL);\r
-\r
- const Decl *D = getCursorDecl(C);\r
- const ASTContext &Context = getCursorContext(C);\r
- const RawComment *RC = Context.getRawCommentForAnyRedecl(D);\r
-\r
- if (RC) {\r
- StringRef BriefText = RC->getBriefText(Context);\r
-\r
- // Don't duplicate the string because RawComment ensures that this memory\r
- // will not go away.\r
- return createCXString(BriefText, false);\r
- }\r
-\r
- return createCXString((const char *) NULL);\r
-}\r
-\r
-CXComment clang_Cursor_getParsedComment(CXCursor C) {\r
- if (!clang_isDeclaration(C.kind))\r
- return cxcomment::createCXComment(NULL, NULL);\r
-\r
- const Decl *D = getCursorDecl(C);\r
- const ASTContext &Context = getCursorContext(C);\r
- const comments::FullComment *FC = Context.getCommentForDecl(D, /*PP=*/ NULL);\r
-\r
- return cxcomment::createCXComment(FC, getCursorTU(C));\r
-}\r
-\r
-CXModule clang_Cursor_getModule(CXCursor C) {\r
- if (C.kind == CXCursor_ModuleImportDecl) {\r
- if (ImportDecl *ImportD = dyn_cast_or_null<ImportDecl>(getCursorDecl(C)))\r
- return ImportD->getImportedModule();\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-CXModule clang_Module_getParent(CXModule CXMod) {\r
- if (!CXMod)\r
- return 0;\r
- Module *Mod = static_cast<Module*>(CXMod);\r
- return Mod->Parent;\r
-}\r
-\r
-CXString clang_Module_getName(CXModule CXMod) {\r
- if (!CXMod)\r
- return createCXString("");\r
- Module *Mod = static_cast<Module*>(CXMod);\r
- return createCXString(Mod->Name);\r
-}\r
-\r
-CXString clang_Module_getFullName(CXModule CXMod) {\r
- if (!CXMod)\r
- return createCXString("");\r
- Module *Mod = static_cast<Module*>(CXMod);\r
- return createCXString(Mod->getFullModuleName());\r
-}\r
-\r
-unsigned clang_Module_getNumTopLevelHeaders(CXModule CXMod) {\r
- if (!CXMod)\r
- return 0;\r
- Module *Mod = static_cast<Module*>(CXMod);\r
- return Mod->TopHeaders.size();\r
-}\r
-\r
-CXFile clang_Module_getTopLevelHeader(CXModule CXMod, unsigned Index) {\r
- if (!CXMod)\r
- return 0;\r
- Module *Mod = static_cast<Module*>(CXMod);\r
-\r
- if (Index < Mod->TopHeaders.size())\r
- return const_cast<FileEntry *>(Mod->TopHeaders[Index]);\r
-\r
- return 0;\r
-}\r
-\r
-} // end: extern "C"\r
-\r
-//===----------------------------------------------------------------------===//\r
-// C++ AST instrospection.\r
-//===----------------------------------------------------------------------===//\r
-\r
-extern "C" {\r
-unsigned clang_CXXMethod_isStatic(CXCursor C) {\r
- if (!clang_isDeclaration(C.kind))\r
- return 0;\r
- \r
- CXXMethodDecl *Method = 0;\r
- Decl *D = cxcursor::getCursorDecl(C);\r
- if (FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))\r
- Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());\r
- else\r
- Method = dyn_cast_or_null<CXXMethodDecl>(D);\r
- return (Method && Method->isStatic()) ? 1 : 0;\r
-}\r
-\r
-unsigned clang_CXXMethod_isVirtual(CXCursor C) {\r
- if (!clang_isDeclaration(C.kind))\r
- return 0;\r
- \r
- CXXMethodDecl *Method = 0;\r
- Decl *D = cxcursor::getCursorDecl(C);\r
- if (FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))\r
- Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());\r
- else\r
- Method = dyn_cast_or_null<CXXMethodDecl>(D);\r
- return (Method && Method->isVirtual()) ? 1 : 0;\r
-}\r
-} // end: extern "C"\r
-\r
-//===----------------------------------------------------------------------===//\r
-// Attribute introspection.\r
-//===----------------------------------------------------------------------===//\r
-\r
-extern "C" {\r
-CXType clang_getIBOutletCollectionType(CXCursor C) {\r
- if (C.kind != CXCursor_IBOutletCollectionAttr)\r
- return cxtype::MakeCXType(QualType(), cxcursor::getCursorTU(C));\r
- \r
- IBOutletCollectionAttr *A =\r
- cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(C));\r
- \r
- return cxtype::MakeCXType(A->getInterface(), cxcursor::getCursorTU(C)); \r
-}\r
-} // end: extern "C"\r
-\r
-//===----------------------------------------------------------------------===//\r
-// Inspecting memory usage.\r
-//===----------------------------------------------------------------------===//\r
-\r
-typedef std::vector<CXTUResourceUsageEntry> MemUsageEntries;\r
-\r
-static inline void createCXTUResourceUsageEntry(MemUsageEntries &entries,\r
- enum CXTUResourceUsageKind k,\r
- unsigned long amount) {\r
- CXTUResourceUsageEntry entry = { k, amount };\r
- entries.push_back(entry);\r
-}\r
-\r
-extern "C" {\r
-\r
-const char *clang_getTUResourceUsageName(CXTUResourceUsageKind kind) {\r
- const char *str = "";\r
- switch (kind) {\r
- case CXTUResourceUsage_AST:\r
- str = "ASTContext: expressions, declarations, and types"; \r
- break;\r
- case CXTUResourceUsage_Identifiers:\r
- str = "ASTContext: identifiers";\r
- break;\r
- case CXTUResourceUsage_Selectors:\r
- str = "ASTContext: selectors";\r
- break;\r
- case CXTUResourceUsage_GlobalCompletionResults:\r
- str = "Code completion: cached global results";\r
- break;\r
- case CXTUResourceUsage_SourceManagerContentCache:\r
- str = "SourceManager: content cache allocator";\r
- break;\r
- case CXTUResourceUsage_AST_SideTables:\r
- str = "ASTContext: side tables";\r
- break;\r
- case CXTUResourceUsage_SourceManager_Membuffer_Malloc:\r
- str = "SourceManager: malloc'ed memory buffers";\r
- break;\r
- case CXTUResourceUsage_SourceManager_Membuffer_MMap:\r
- str = "SourceManager: mmap'ed memory buffers";\r
- break;\r
- case CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc:\r
- str = "ExternalASTSource: malloc'ed memory buffers";\r
- break;\r
- case CXTUResourceUsage_ExternalASTSource_Membuffer_MMap:\r
- str = "ExternalASTSource: mmap'ed memory buffers";\r
- break;\r
- case CXTUResourceUsage_Preprocessor:\r
- str = "Preprocessor: malloc'ed memory";\r
- break;\r
- case CXTUResourceUsage_PreprocessingRecord:\r
- str = "Preprocessor: PreprocessingRecord";\r
- break;\r
- case CXTUResourceUsage_SourceManager_DataStructures:\r
- str = "SourceManager: data structures and tables";\r
- break;\r
- case CXTUResourceUsage_Preprocessor_HeaderSearch:\r
- str = "Preprocessor: header search tables";\r
- break;\r
- }\r
- return str;\r
-}\r
-\r
-CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU) {\r
- if (!TU) {\r
- CXTUResourceUsage usage = { (void*) 0, 0, 0 };\r
- return usage;\r
- }\r
- \r
- ASTUnit *astUnit = static_cast<ASTUnit*>(TU->TUData);\r
- OwningPtr<MemUsageEntries> entries(new MemUsageEntries());\r
- ASTContext &astContext = astUnit->getASTContext();\r
- \r
- // How much memory is used by AST nodes and types?\r
- createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_AST,\r
- (unsigned long) astContext.getASTAllocatedMemory());\r
-\r
- // How much memory is used by identifiers?\r
- createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_Identifiers,\r
- (unsigned long) astContext.Idents.getAllocator().getTotalMemory());\r
-\r
- // How much memory is used for selectors?\r
- createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_Selectors,\r
- (unsigned long) astContext.Selectors.getTotalMemory());\r
- \r
- // How much memory is used by ASTContext's side tables?\r
- createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_AST_SideTables,\r
- (unsigned long) astContext.getSideTableAllocatedMemory());\r
- \r
- // How much memory is used for caching global code completion results?\r
- unsigned long completionBytes = 0;\r
- if (GlobalCodeCompletionAllocator *completionAllocator =\r
- astUnit->getCachedCompletionAllocator().getPtr()) {\r
- completionBytes = completionAllocator->getTotalMemory();\r
- }\r
- createCXTUResourceUsageEntry(*entries,\r
- CXTUResourceUsage_GlobalCompletionResults,\r
- completionBytes);\r
- \r
- // How much memory is being used by SourceManager's content cache?\r
- createCXTUResourceUsageEntry(*entries,\r
- CXTUResourceUsage_SourceManagerContentCache,\r
- (unsigned long) astContext.getSourceManager().getContentCacheSize());\r
- \r
- // How much memory is being used by the MemoryBuffer's in SourceManager?\r
- const SourceManager::MemoryBufferSizes &srcBufs =\r
- astUnit->getSourceManager().getMemoryBufferSizes();\r
- \r
- createCXTUResourceUsageEntry(*entries,\r
- CXTUResourceUsage_SourceManager_Membuffer_Malloc,\r
- (unsigned long) srcBufs.malloc_bytes);\r
- createCXTUResourceUsageEntry(*entries,\r
- CXTUResourceUsage_SourceManager_Membuffer_MMap,\r
- (unsigned long) srcBufs.mmap_bytes);\r
- createCXTUResourceUsageEntry(*entries,\r
- CXTUResourceUsage_SourceManager_DataStructures,\r
- (unsigned long) astContext.getSourceManager()\r
- .getDataStructureSizes());\r
- \r
- // How much memory is being used by the ExternalASTSource?\r
- if (ExternalASTSource *esrc = astContext.getExternalSource()) {\r
- const ExternalASTSource::MemoryBufferSizes &sizes =\r
- esrc->getMemoryBufferSizes();\r
- \r
- createCXTUResourceUsageEntry(*entries,\r
- CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc,\r
- (unsigned long) sizes.malloc_bytes);\r
- createCXTUResourceUsageEntry(*entries,\r
- CXTUResourceUsage_ExternalASTSource_Membuffer_MMap,\r
- (unsigned long) sizes.mmap_bytes);\r
- }\r
- \r
- // How much memory is being used by the Preprocessor?\r
- Preprocessor &pp = astUnit->getPreprocessor();\r
- createCXTUResourceUsageEntry(*entries,\r
- CXTUResourceUsage_Preprocessor,\r
- pp.getTotalMemory());\r
- \r
- if (PreprocessingRecord *pRec = pp.getPreprocessingRecord()) {\r
- createCXTUResourceUsageEntry(*entries,\r
- CXTUResourceUsage_PreprocessingRecord,\r
- pRec->getTotalMemory()); \r
- }\r
- \r
- createCXTUResourceUsageEntry(*entries,\r
- CXTUResourceUsage_Preprocessor_HeaderSearch,\r
- pp.getHeaderSearchInfo().getTotalMemory());\r
- \r
- CXTUResourceUsage usage = { (void*) entries.get(),\r
- (unsigned) entries->size(),\r
- entries->size() ? &(*entries)[0] : 0 };\r
- entries.take();\r
- return usage;\r
-}\r
-\r
-void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage) {\r
- if (usage.data)\r
- delete (MemUsageEntries*) usage.data;\r
-}\r
-\r
-} // end extern "C"\r
-\r
-void clang::PrintLibclangResourceUsage(CXTranslationUnit TU) {\r
- CXTUResourceUsage Usage = clang_getCXTUResourceUsage(TU);\r
- for (unsigned I = 0; I != Usage.numEntries; ++I)\r
- fprintf(stderr, " %s: %lu\n", \r
- clang_getTUResourceUsageName(Usage.entries[I].kind),\r
- Usage.entries[I].amount);\r
- \r
- clang_disposeCXTUResourceUsage(Usage);\r
-}\r
-\r
-//===----------------------------------------------------------------------===//\r
-// Misc. utility functions.\r
-//===----------------------------------------------------------------------===//\r
-\r
-/// Default to using an 8 MB stack size on "safety" threads.\r
-static unsigned SafetyStackThreadSize = 8 << 20;\r
-\r
-namespace clang {\r
-\r
-bool RunSafely(llvm::CrashRecoveryContext &CRC,\r
- void (*Fn)(void*), void *UserData,\r
- unsigned Size) {\r
- if (!Size)\r
- Size = GetSafetyThreadStackSize();\r
- if (Size)\r
- return CRC.RunSafelyOnThread(Fn, UserData, Size);\r
- return CRC.RunSafely(Fn, UserData);\r
-}\r
-\r
-unsigned GetSafetyThreadStackSize() {\r
- return SafetyStackThreadSize;\r
-}\r
-\r
-void SetSafetyThreadStackSize(unsigned Value) {\r
- SafetyStackThreadSize = Value;\r
-}\r
-\r
-}\r
-\r
-void clang::setThreadBackgroundPriority() {\r
- if (getenv("LIBCLANG_BGPRIO_DISABLE"))\r
- return;\r
-\r
- // FIXME: Move to llvm/Support and make it cross-platform.\r
-#ifdef __APPLE__\r
- setpriority(PRIO_DARWIN_THREAD, 0, PRIO_DARWIN_BG);\r
-#endif\r
-}\r
-\r
-void cxindex::printDiagsToStderr(ASTUnit *Unit) {\r
- if (!Unit)\r
- return;\r
-\r
- for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(), \r
- DEnd = Unit->stored_diag_end();\r
- D != DEnd; ++D) {\r
- CXStoredDiagnostic Diag(*D, Unit->getASTContext().getLangOpts());\r
- CXString Msg = clang_formatDiagnostic(&Diag,\r
- clang_defaultDiagnosticDisplayOptions());\r
- fprintf(stderr, "%s\n", clang_getCString(Msg));\r
- clang_disposeString(Msg);\r
- }\r
-#ifdef LLVM_ON_WIN32\r
- // On Windows, force a flush, since there may be multiple copies of\r
- // stderr and stdout in the file system, all with different buffers\r
- // but writing to the same device.\r
- fflush(stderr);\r
-#endif\r
-}\r
-\r
-extern "C" {\r
-\r
-CXString clang_getClangVersion() {\r
- return createCXString(getClangFullVersion());\r
-}\r
-\r
-} // end: extern "C"\r
-\r
+//===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the main API hooks in the Clang-C Source Indexing
+// library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CIndexDiagnostic.h"
+#include "CXComment.h"
+#include "CXCursor.h"
+#include "CXSourceLocation.h"
+#include "CXString.h"
+#include "CXTranslationUnit.h"
+#include "CXType.h"
+#include "CursorVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/Version.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/Threading.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::cxcursor;
+using namespace clang::cxstring;
+using namespace clang::cxtu;
+using namespace clang::cxindex;
+
+CXTranslationUnit cxtu::MakeCXTranslationUnit(CIndexer *CIdx, ASTUnit *TU) {
+ if (!TU)
+ return 0;
+ CXTranslationUnit D = new CXTranslationUnitImpl();
+ D->CIdx = CIdx;
+ D->TUData = TU;
+ D->StringPool = createCXStringPool();
+ D->Diagnostics = 0;
+ D->OverridenCursorsPool = createOverridenCXCursorsPool();
+ return D;
+}
+
+cxtu::CXTUOwner::~CXTUOwner() {
+ if (TU)
+ clang_disposeTranslationUnit(TU);
+}
+
+/// \brief Compare two source ranges to determine their relative position in
+/// the translation unit.
+static RangeComparisonResult RangeCompare(SourceManager &SM,
+ SourceRange R1,
+ SourceRange R2) {
+ assert(R1.isValid() && "First range is invalid?");
+ assert(R2.isValid() && "Second range is invalid?");
+ if (R1.getEnd() != R2.getBegin() &&
+ SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin()))
+ return RangeBefore;
+ if (R2.getEnd() != R1.getBegin() &&
+ SM.isBeforeInTranslationUnit(R2.getEnd(), R1.getBegin()))
+ return RangeAfter;
+ return RangeOverlap;
+}
+
+/// \brief Determine if a source location falls within, before, or after a
+/// a given source range.
+static RangeComparisonResult LocationCompare(SourceManager &SM,
+ SourceLocation L, SourceRange R) {
+ assert(R.isValid() && "First range is invalid?");
+ assert(L.isValid() && "Second range is invalid?");
+ if (L == R.getBegin() || L == R.getEnd())
+ return RangeOverlap;
+ if (SM.isBeforeInTranslationUnit(L, R.getBegin()))
+ return RangeBefore;
+ if (SM.isBeforeInTranslationUnit(R.getEnd(), L))
+ return RangeAfter;
+ return RangeOverlap;
+}
+
+/// \brief Translate a Clang source range into a CIndex source range.
+///
+/// Clang internally represents ranges where the end location points to the
+/// start of the token at the end. However, for external clients it is more
+/// useful to have a CXSourceRange be a proper half-open interval. This routine
+/// does the appropriate translation.
+CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,
+ const LangOptions &LangOpts,
+ const CharSourceRange &R) {
+ // We want the last character in this location, so we will adjust the
+ // location accordingly.
+ SourceLocation EndLoc = R.getEnd();
+ if (EndLoc.isValid() && EndLoc.isMacroID() && !SM.isMacroArgExpansion(EndLoc))
+ EndLoc = SM.getExpansionRange(EndLoc).second;
+ if (R.isTokenRange() && !EndLoc.isInvalid()) {
+ unsigned Length = Lexer::MeasureTokenLength(SM.getSpellingLoc(EndLoc),
+ SM, LangOpts);
+ EndLoc = EndLoc.getLocWithOffset(Length);
+ }
+
+ CXSourceRange Result = { { (void *)&SM, (void *)&LangOpts },
+ R.getBegin().getRawEncoding(),
+ EndLoc.getRawEncoding() };
+ return Result;
+}
+
+//===----------------------------------------------------------------------===//
+// Cursor visitor.
+//===----------------------------------------------------------------------===//
+
+static SourceRange getRawCursorExtent(CXCursor C);
+static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr);
+
+
+RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {
+ return RangeCompare(AU->getSourceManager(), R, RegionOfInterest);
+}
+
+/// \brief Visit the given cursor and, if requested by the visitor,
+/// its children.
+///
+/// \param Cursor the cursor to visit.
+///
+/// \param CheckedRegionOfInterest if true, then the caller already checked
+/// that this cursor is within the region of interest.
+///
+/// \returns true if the visitation should be aborted, false if it
+/// should continue.
+bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) {
+ if (clang_isInvalid(Cursor.kind))
+ return false;
+
+ if (clang_isDeclaration(Cursor.kind)) {
+ Decl *D = getCursorDecl(Cursor);
+ if (!D) {
+ assert(0 && "Invalid declaration cursor");
+ return true; // abort.
+ }
+
+ // Ignore implicit declarations, unless it's an objc method because
+ // currently we should report implicit methods for properties when indexing.
+ if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
+ return false;
+ }
+
+ // If we have a range of interest, and this cursor doesn't intersect with it,
+ // we're done.
+ if (RegionOfInterest.isValid() && !CheckedRegionOfInterest) {
+ SourceRange Range = getRawCursorExtent(Cursor);
+ if (Range.isInvalid() || CompareRegionOfInterest(Range))
+ return false;
+ }
+
+ switch (Visitor(Cursor, Parent, ClientData)) {
+ case CXChildVisit_Break:
+ return true;
+
+ case CXChildVisit_Continue:
+ return false;
+
+ case CXChildVisit_Recurse: {
+ bool ret = VisitChildren(Cursor);
+ if (PostChildrenVisitor)
+ if (PostChildrenVisitor(Cursor, ClientData))
+ return true;
+ return ret;
+ }
+ }
+
+ llvm_unreachable("Invalid CXChildVisitResult!");
+}
+
+static bool visitPreprocessedEntitiesInRange(SourceRange R,
+ PreprocessingRecord &PPRec,
+ CursorVisitor &Visitor) {
+ SourceManager &SM = Visitor.getASTUnit()->getSourceManager();
+ FileID FID;
+
+ if (!Visitor.shouldVisitIncludedEntities()) {
+ // If the begin/end of the range lie in the same FileID, do the optimization
+ // where we skip preprocessed entities that do not come from the same FileID.
+ FID = SM.getFileID(SM.getFileLoc(R.getBegin()));
+ if (FID != SM.getFileID(SM.getFileLoc(R.getEnd())))
+ FID = FileID();
+ }
+
+ std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
+ Entities = PPRec.getPreprocessedEntitiesInRange(R);
+ return Visitor.visitPreprocessedEntities(Entities.first, Entities.second,
+ PPRec, FID);
+}
+
+void CursorVisitor::visitFileRegion() {
+ if (RegionOfInterest.isInvalid())
+ return;
+
+ ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData);
+ SourceManager &SM = Unit->getSourceManager();
+
+ std::pair<FileID, unsigned>
+ Begin = SM.getDecomposedLoc(SM.getFileLoc(RegionOfInterest.getBegin())),
+ End = SM.getDecomposedLoc(SM.getFileLoc(RegionOfInterest.getEnd()));
+
+ if (End.first != Begin.first) {
+ // If the end does not reside in the same file, try to recover by
+ // picking the end of the file of begin location.
+ End.first = Begin.first;
+ End.second = SM.getFileIDSize(Begin.first);
+ }
+
+ assert(Begin.first == End.first);
+ if (Begin.second > End.second)
+ return;
+
+ FileID File = Begin.first;
+ unsigned Offset = Begin.second;
+ unsigned Length = End.second - Begin.second;
+
+ if (!VisitDeclsOnly && !VisitPreprocessorLast)
+ if (visitPreprocessedEntitiesInRegion())
+ return; // visitation break.
+
+ visitDeclsFromFileRegion(File, Offset, Length);
+
+ if (!VisitDeclsOnly && VisitPreprocessorLast)
+ visitPreprocessedEntitiesInRegion();
+}
+
+static bool isInLexicalContext(Decl *D, DeclContext *DC) {
+ if (!DC)
+ return false;
+
+ for (DeclContext *DeclDC = D->getLexicalDeclContext();
+ DeclDC; DeclDC = DeclDC->getLexicalParent()) {
+ if (DeclDC == DC)
+ return true;
+ }
+ return false;
+}
+
+void CursorVisitor::visitDeclsFromFileRegion(FileID File,
+ unsigned Offset, unsigned Length) {
+ ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData);
+ SourceManager &SM = Unit->getSourceManager();
+ SourceRange Range = RegionOfInterest;
+
+ SmallVector<Decl *, 16> Decls;
+ Unit->findFileRegionDecls(File, Offset, Length, Decls);
+
+ // If we didn't find any file level decls for the file, try looking at the
+ // file that it was included from.
+ while (Decls.empty() || Decls.front()->isTopLevelDeclInObjCContainer()) {
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &SLEntry = SM.getSLocEntry(File, &Invalid);
+ if (Invalid)
+ return;
+
+ SourceLocation Outer;
+ if (SLEntry.isFile())
+ Outer = SLEntry.getFile().getIncludeLoc();
+ else
+ Outer = SLEntry.getExpansion().getExpansionLocStart();
+ if (Outer.isInvalid())
+ return;
+
+ llvm::tie(File, Offset) = SM.getDecomposedExpansionLoc(Outer);
+ Length = 0;
+ Unit->findFileRegionDecls(File, Offset, Length, Decls);
+ }
+
+ assert(!Decls.empty());
+
+ bool VisitedAtLeastOnce = false;
+ DeclContext *CurDC = 0;
+ SmallVector<Decl *, 16>::iterator DIt = Decls.begin();
+ for (SmallVector<Decl *, 16>::iterator DE = Decls.end(); DIt != DE; ++DIt) {
+ Decl *D = *DIt;
+ if (D->getSourceRange().isInvalid())
+ continue;
+
+ if (isInLexicalContext(D, CurDC))
+ continue;
+
+ CurDC = dyn_cast<DeclContext>(D);
+
+ if (TagDecl *TD = dyn_cast<TagDecl>(D))
+ if (!TD->isFreeStanding())
+ continue;
+
+ RangeComparisonResult CompRes = RangeCompare(SM, D->getSourceRange(),Range);
+ if (CompRes == RangeBefore)
+ continue;
+ if (CompRes == RangeAfter)
+ break;
+
+ assert(CompRes == RangeOverlap);
+ VisitedAtLeastOnce = true;
+
+ if (isa<ObjCContainerDecl>(D)) {
+ FileDI_current = &DIt;
+ FileDE_current = DE;
+ } else {
+ FileDI_current = 0;
+ }
+
+ if (Visit(MakeCXCursor(D, TU, Range), /*CheckedRegionOfInterest=*/true))
+ break;
+ }
+
+ if (VisitedAtLeastOnce)
+ return;
+
+ // No Decls overlapped with the range. Move up the lexical context until there
+ // is a context that contains the range or we reach the translation unit
+ // level.
+ DeclContext *DC = DIt == Decls.begin() ? (*DIt)->getLexicalDeclContext()
+ : (*(DIt-1))->getLexicalDeclContext();
+
+ while (DC && !DC->isTranslationUnit()) {
+ Decl *D = cast<Decl>(DC);
+ SourceRange CurDeclRange = D->getSourceRange();
+ if (CurDeclRange.isInvalid())
+ break;
+
+ if (RangeCompare(SM, CurDeclRange, Range) == RangeOverlap) {
+ Visit(MakeCXCursor(D, TU, Range), /*CheckedRegionOfInterest=*/true);
+ break;
+ }
+
+ DC = D->getLexicalDeclContext();
+ }
+}
+
+bool CursorVisitor::visitPreprocessedEntitiesInRegion() {
+ if (!AU->getPreprocessor().getPreprocessingRecord())
+ return false;
+
+ PreprocessingRecord &PPRec
+ = *AU->getPreprocessor().getPreprocessingRecord();
+ SourceManager &SM = AU->getSourceManager();
+
+ if (RegionOfInterest.isValid()) {
+ SourceRange MappedRange = AU->mapRangeToPreamble(RegionOfInterest);
+ SourceLocation B = MappedRange.getBegin();
+ SourceLocation E = MappedRange.getEnd();
+
+ if (AU->isInPreambleFileID(B)) {
+ if (SM.isLoadedSourceLocation(E))
+ return visitPreprocessedEntitiesInRange(SourceRange(B, E),
+ PPRec, *this);
+
+ // Beginning of range lies in the preamble but it also extends beyond
+ // it into the main file. Split the range into 2 parts, one covering
+ // the preamble and another covering the main file. This allows subsequent
+ // calls to visitPreprocessedEntitiesInRange to accept a source range that
+ // lies in the same FileID, allowing it to skip preprocessed entities that
+ // do not come from the same FileID.
+ bool breaked =
+ visitPreprocessedEntitiesInRange(
+ SourceRange(B, AU->getEndOfPreambleFileID()),
+ PPRec, *this);
+ if (breaked) return true;
+ return visitPreprocessedEntitiesInRange(
+ SourceRange(AU->getStartOfMainFileID(), E),
+ PPRec, *this);
+ }
+
+ return visitPreprocessedEntitiesInRange(SourceRange(B, E), PPRec, *this);
+ }
+
+ bool OnlyLocalDecls
+ = !AU->isMainFileAST() && AU->getOnlyLocalDecls();
+
+ if (OnlyLocalDecls)
+ return visitPreprocessedEntities(PPRec.local_begin(), PPRec.local_end(),
+ PPRec);
+
+ return visitPreprocessedEntities(PPRec.begin(), PPRec.end(), PPRec);
+}
+
+template<typename InputIterator>
+bool CursorVisitor::visitPreprocessedEntities(InputIterator First,
+ InputIterator Last,
+ PreprocessingRecord &PPRec,
+ FileID FID) {
+ for (; First != Last; ++First) {
+ if (!FID.isInvalid() && !PPRec.isEntityInFileID(First, FID))
+ continue;
+
+ PreprocessedEntity *PPE = *First;
+ if (MacroExpansion *ME = dyn_cast<MacroExpansion>(PPE)) {
+ if (Visit(MakeMacroExpansionCursor(ME, TU)))
+ return true;
+
+ continue;
+ }
+
+ if (MacroDefinition *MD = dyn_cast<MacroDefinition>(PPE)) {
+ if (Visit(MakeMacroDefinitionCursor(MD, TU)))
+ return true;
+
+ continue;
+ }
+
+ if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) {
+ if (Visit(MakeInclusionDirectiveCursor(ID, TU)))
+ return true;
+
+ continue;
+ }
+ }
+
+ return false;
+}
+
+/// \brief Visit the children of the given cursor.
+///
+/// \returns true if the visitation should be aborted, false if it
+/// should continue.
+bool CursorVisitor::VisitChildren(CXCursor Cursor) {
+ if (clang_isReference(Cursor.kind) &&
+ Cursor.kind != CXCursor_CXXBaseSpecifier) {
+ // By definition, references have no children.
+ return false;
+ }
+
+ // Set the Parent field to Cursor, then back to its old value once we're
+ // done.
+ SetParentRAII SetParent(Parent, StmtParent, Cursor);
+
+ if (clang_isDeclaration(Cursor.kind)) {
+ Decl *D = getCursorDecl(Cursor);
+ if (!D)
+ return false;
+
+ return VisitAttributes(D) || Visit(D);
+ }
+
+ if (clang_isStatement(Cursor.kind)) {
+ if (Stmt *S = getCursorStmt(Cursor))
+ return Visit(S);
+
+ return false;
+ }
+
+ if (clang_isExpression(Cursor.kind)) {
+ if (Expr *E = getCursorExpr(Cursor))
+ return Visit(E);
+
+ return false;
+ }
+
+ if (clang_isTranslationUnit(Cursor.kind)) {
+ CXTranslationUnit tu = getCursorTU(Cursor);
+ ASTUnit *CXXUnit = static_cast<ASTUnit*>(tu->TUData);
+
+ int VisitOrder[2] = { VisitPreprocessorLast, !VisitPreprocessorLast };
+ for (unsigned I = 0; I != 2; ++I) {
+ if (VisitOrder[I]) {
+ if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
+ RegionOfInterest.isInvalid()) {
+ for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),
+ TLEnd = CXXUnit->top_level_end();
+ TL != TLEnd; ++TL) {
+ if (Visit(MakeCXCursor(*TL, tu, RegionOfInterest), true))
+ return true;
+ }
+ } else if (VisitDeclContext(
+ CXXUnit->getASTContext().getTranslationUnitDecl()))
+ return true;
+ continue;
+ }
+
+ // Walk the preprocessing record.
+ if (CXXUnit->getPreprocessor().getPreprocessingRecord())
+ visitPreprocessedEntitiesInRegion();
+ }
+
+ return false;
+ }
+
+ if (Cursor.kind == CXCursor_CXXBaseSpecifier) {
+ if (CXXBaseSpecifier *Base = getCursorCXXBaseSpecifier(Cursor)) {
+ if (TypeSourceInfo *BaseTSInfo = Base->getTypeSourceInfo()) {
+ return Visit(BaseTSInfo->getTypeLoc());
+ }
+ }
+ }
+
+ if (Cursor.kind == CXCursor_IBOutletCollectionAttr) {
+ IBOutletCollectionAttr *A =
+ cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(Cursor));
+ if (const ObjCInterfaceType *InterT = A->getInterface()->getAs<ObjCInterfaceType>())
+ return Visit(cxcursor::MakeCursorObjCClassRef(InterT->getInterface(),
+ A->getInterfaceLoc(), TU));
+ }
+
+ // Nothing to visit at the moment.
+ return false;
+}
+
+bool CursorVisitor::VisitBlockDecl(BlockDecl *B) {
+ if (TypeSourceInfo *TSInfo = B->getSignatureAsWritten())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ if (Stmt *Body = B->getBody())
+ return Visit(MakeCXCursor(Body, StmtParent, TU, RegionOfInterest));
+
+ return false;
+}
+
+llvm::Optional<bool> CursorVisitor::shouldVisitCursor(CXCursor Cursor) {
+ if (RegionOfInterest.isValid()) {
+ SourceRange Range = getFullCursorExtent(Cursor, AU->getSourceManager());
+ if (Range.isInvalid())
+ return llvm::Optional<bool>();
+
+ switch (CompareRegionOfInterest(Range)) {
+ case RangeBefore:
+ // This declaration comes before the region of interest; skip it.
+ return llvm::Optional<bool>();
+
+ case RangeAfter:
+ // This declaration comes after the region of interest; we're done.
+ return false;
+
+ case RangeOverlap:
+ // This declaration overlaps the region of interest; visit it.
+ break;
+ }
+ }
+ return true;
+}
+
+bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
+ DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
+
+ // FIXME: Eventually remove. This part of a hack to support proper
+ // iteration over all Decls contained lexically within an ObjC container.
+ SaveAndRestore<DeclContext::decl_iterator*> DI_saved(DI_current, &I);
+ SaveAndRestore<DeclContext::decl_iterator> DE_saved(DE_current, E);
+
+ for ( ; I != E; ++I) {
+ Decl *D = *I;
+ if (D->getLexicalDeclContext() != DC)
+ continue;
+ CXCursor Cursor = MakeCXCursor(D, TU, RegionOfInterest);
+
+ // Ignore synthesized ivars here, otherwise if we have something like:
+ // @synthesize prop = _prop;
+ // and '_prop' is not declared, we will encounter a '_prop' ivar before
+ // encountering the 'prop' synthesize declaration and we will think that
+ // we passed the region-of-interest.
+ if (ObjCIvarDecl *ivarD = dyn_cast<ObjCIvarDecl>(D)) {
+ if (ivarD->getSynthesize())
+ continue;
+ }
+
+ // FIXME: ObjCClassRef/ObjCProtocolRef for forward class/protocol
+ // declarations is a mismatch with the compiler semantics.
+ if (Cursor.kind == CXCursor_ObjCInterfaceDecl) {
+ ObjCInterfaceDecl *ID = cast<ObjCInterfaceDecl>(D);
+ if (!ID->isThisDeclarationADefinition())
+ Cursor = MakeCursorObjCClassRef(ID, ID->getLocation(), TU);
+
+ } else if (Cursor.kind == CXCursor_ObjCProtocolDecl) {
+ ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D);
+ if (!PD->isThisDeclarationADefinition())
+ Cursor = MakeCursorObjCProtocolRef(PD, PD->getLocation(), TU);
+ }
+
+ const llvm::Optional<bool> &V = shouldVisitCursor(Cursor);
+ if (!V.hasValue())
+ continue;
+ if (!V.getValue())
+ return false;
+ if (Visit(Cursor, true))
+ return true;
+ }
+ return false;
+}
+
+bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+ llvm_unreachable("Translation units are visited directly by Visit()");
+}
+
+bool CursorVisitor::VisitTypeAliasDecl(TypeAliasDecl *D) {
+ if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
+bool CursorVisitor::VisitTypedefDecl(TypedefDecl *D) {
+ if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
+bool CursorVisitor::VisitTagDecl(TagDecl *D) {
+ return VisitDeclContext(D);
+}
+
+bool CursorVisitor::VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D) {
+ bool ShouldVisitBody = false;
+ switch (D->getSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ // Nothing to visit
+ return false;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ break;
+
+ case TSK_ExplicitSpecialization:
+ ShouldVisitBody = true;
+ break;
+ }
+
+ // Visit the template arguments used in the specialization.
+ if (TypeSourceInfo *SpecType = D->getTypeAsWritten()) {
+ TypeLoc TL = SpecType->getTypeLoc();
+ if (TemplateSpecializationTypeLoc *TSTLoc
+ = dyn_cast<TemplateSpecializationTypeLoc>(&TL)) {
+ for (unsigned I = 0, N = TSTLoc->getNumArgs(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TSTLoc->getArgLoc(I)))
+ return true;
+ }
+ }
+
+ if (ShouldVisitBody && VisitCXXRecordDecl(D))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the TagDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ // Visit the partial specialization arguments.
+ const TemplateArgumentLoc *TemplateArgs = D->getTemplateArgsAsWritten();
+ for (unsigned I = 0, N = D->getNumTemplateArgsAsWritten(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TemplateArgs[I]))
+ return true;
+
+ return VisitCXXRecordDecl(D);
+}
+
+bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ // Visit the default argument.
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
+ if (TypeSourceInfo *DefArg = D->getDefaultArgumentInfo())
+ if (Visit(DefArg->getTypeLoc()))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
+ if (Expr *Init = D->getInitExpr())
+ return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));
+ return false;
+}
+
+bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
+ if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ // Visit the nested-name-specifier, if present.
+ if (NestedNameSpecifierLoc QualifierLoc = DD->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ return false;
+}
+
+/// \brief Compare two base or member initializers based on their source order.
+static int CompareCXXCtorInitializers(const void* Xp, const void *Yp) {
+ CXXCtorInitializer const * const *X
+ = static_cast<CXXCtorInitializer const * const *>(Xp);
+ CXXCtorInitializer const * const *Y
+ = static_cast<CXXCtorInitializer const * const *>(Yp);
+
+ if ((*X)->getSourceOrder() < (*Y)->getSourceOrder())
+ return -1;
+ else if ((*X)->getSourceOrder() > (*Y)->getSourceOrder())
+ return 1;
+ else
+ return 0;
+}
+
+bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
+ if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {
+ // Visit the function declaration's syntactic components in the order
+ // written. This requires a bit of work.
+ TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
+ FunctionTypeLoc *FTL = dyn_cast<FunctionTypeLoc>(&TL);
+
+ // If we have a function declared directly (without the use of a typedef),
+ // visit just the return type. Otherwise, just visit the function's type
+ // now.
+ if ((FTL && !isa<CXXConversionDecl>(ND) && Visit(FTL->getResultLoc())) ||
+ (!FTL && Visit(TL)))
+ return true;
+
+ // Visit the nested-name-specifier, if present.
+ if (NestedNameSpecifierLoc QualifierLoc = ND->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(ND->getNameInfo()))
+ return true;
+
+ // FIXME: Visit explicitly-specified template arguments!
+
+ // Visit the function parameters, if we have a function type.
+ if (FTL && VisitFunctionTypeLoc(*FTL, true))
+ return true;
+
+ // FIXME: Attributes?
+ }
+
+ if (ND->doesThisDeclarationHaveABody() && !ND->isLateTemplateParsed()) {
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ND)) {
+ // Find the initializers that were written in the source.
+ SmallVector<CXXCtorInitializer *, 4> WrittenInits;
+ for (CXXConstructorDecl::init_iterator I = Constructor->init_begin(),
+ IEnd = Constructor->init_end();
+ I != IEnd; ++I) {
+ if (!(*I)->isWritten())
+ continue;
+
+ WrittenInits.push_back(*I);
+ }
+
+ // Sort the initializers in source order
+ llvm::array_pod_sort(WrittenInits.begin(), WrittenInits.end(),
+ &CompareCXXCtorInitializers);
+
+ // Visit the initializers in source order
+ for (unsigned I = 0, N = WrittenInits.size(); I != N; ++I) {
+ CXXCtorInitializer *Init = WrittenInits[I];
+ if (Init->isAnyMemberInitializer()) {
+ if (Visit(MakeCursorMemberRef(Init->getAnyMember(),
+ Init->getMemberLocation(), TU)))
+ return true;
+ } else if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) {
+ if (Visit(TInfo->getTypeLoc()))
+ return true;
+ }
+
+ // Visit the initializer value.
+ if (Expr *Initializer = Init->getInit())
+ if (Visit(MakeCXCursor(Initializer, ND, TU, RegionOfInterest)))
+ return true;
+ }
+ }
+
+ if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitFieldDecl(FieldDecl *D) {
+ if (VisitDeclaratorDecl(D))
+ return true;
+
+ if (Expr *BitWidth = D->getBitWidth())
+ return Visit(MakeCXCursor(BitWidth, StmtParent, TU, RegionOfInterest));
+
+ return false;
+}
+
+bool CursorVisitor::VisitVarDecl(VarDecl *D) {
+ if (VisitDeclaratorDecl(D))
+ return true;
+
+ if (Expr *Init = D->getInit())
+ return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));
+
+ return false;
+}
+
+bool CursorVisitor::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+ if (VisitDeclaratorDecl(D))
+ return true;
+
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
+ if (Expr *DefArg = D->getDefaultArgument())
+ return Visit(MakeCXCursor(DefArg, StmtParent, TU, RegionOfInterest));
+
+ return false;
+}
+
+bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the FunctionDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ return VisitFunctionDecl(D->getTemplatedDecl());
+}
+
+bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the TagDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ return VisitCXXRecordDecl(D->getTemplatedDecl());
+}
+
+bool CursorVisitor::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited() &&
+ VisitTemplateArgumentLoc(D->getDefaultArgument()))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
+ if (TypeSourceInfo *TSInfo = ND->getResultTypeSourceInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ for (ObjCMethodDecl::param_iterator P = ND->param_begin(),
+ PEnd = ND->param_end();
+ P != PEnd; ++P) {
+ if (Visit(MakeCXCursor(*P, TU, RegionOfInterest)))
+ return true;
+ }
+
+ if (ND->isThisDeclarationADefinition() &&
+ Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest)))
+ return true;
+
+ return false;
+}
+
+template <typename DeclIt>
+static void addRangedDeclsInContainer(DeclIt *DI_current, DeclIt DE_current,
+ SourceManager &SM, SourceLocation EndLoc,
+ SmallVectorImpl<Decl *> &Decls) {
+ DeclIt next = *DI_current;
+ while (++next != DE_current) {
+ Decl *D_next = *next;
+ if (!D_next)
+ break;
+ SourceLocation L = D_next->getLocStart();
+ if (!L.isValid())
+ break;
+ if (SM.isBeforeInTranslationUnit(L, EndLoc)) {
+ *DI_current = next;
+ Decls.push_back(D_next);
+ continue;
+ }
+ break;
+ }
+}
+
+namespace {
+ struct ContainerDeclsSort {
+ SourceManager &SM;
+ ContainerDeclsSort(SourceManager &sm) : SM(sm) {}
+ bool operator()(Decl *A, Decl *B) {
+ SourceLocation L_A = A->getLocStart();
+ SourceLocation L_B = B->getLocStart();
+ assert(L_A.isValid() && L_B.isValid());
+ return SM.isBeforeInTranslationUnit(L_A, L_B);
+ }
+ };
+}
+
+bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
+ // FIXME: Eventually convert back to just 'VisitDeclContext()'. Essentially
+ // an @implementation can lexically contain Decls that are not properly
+ // nested in the AST. When we identify such cases, we need to retrofit
+ // this nesting here.
+ if (!DI_current && !FileDI_current)
+ return VisitDeclContext(D);
+
+ // Scan the Decls that immediately come after the container
+ // in the current DeclContext. If any fall within the
+ // container's lexical region, stash them into a vector
+ // for later processing.
+ SmallVector<Decl *, 24> DeclsInContainer;
+ SourceLocation EndLoc = D->getSourceRange().getEnd();
+ SourceManager &SM = AU->getSourceManager();
+ if (EndLoc.isValid()) {
+ if (DI_current) {
+ addRangedDeclsInContainer(DI_current, DE_current, SM, EndLoc,
+ DeclsInContainer);
+ } else {
+ addRangedDeclsInContainer(FileDI_current, FileDE_current, SM, EndLoc,
+ DeclsInContainer);
+ }
+ }
+
+ // The common case.
+ if (DeclsInContainer.empty())
+ return VisitDeclContext(D);
+
+ // Get all the Decls in the DeclContext, and sort them with the
+ // additional ones we've collected. Then visit them.
+ for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
+ I!=E; ++I) {
+ Decl *subDecl = *I;
+ if (!subDecl || subDecl->getLexicalDeclContext() != D ||
+ subDecl->getLocStart().isInvalid())
+ continue;
+ DeclsInContainer.push_back(subDecl);
+ }
+
+ // Now sort the Decls so that they appear in lexical order.
+ std::sort(DeclsInContainer.begin(), DeclsInContainer.end(),
+ ContainerDeclsSort(SM));
+
+ // Now visit the decls.
+ for (SmallVectorImpl<Decl*>::iterator I = DeclsInContainer.begin(),
+ E = DeclsInContainer.end(); I != E; ++I) {
+ CXCursor Cursor = MakeCXCursor(*I, TU, RegionOfInterest);
+ const llvm::Optional<bool> &V = shouldVisitCursor(Cursor);
+ if (!V.hasValue())
+ continue;
+ if (!V.getValue())
+ return false;
+ if (Visit(Cursor, true))
+ return true;
+ }
+ return false;
+}
+
+bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
+ if (Visit(MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation(),
+ TU)))
+ return true;
+
+ ObjCCategoryDecl::protocol_loc_iterator PL = ND->protocol_loc_begin();
+ for (ObjCCategoryDecl::protocol_iterator I = ND->protocol_begin(),
+ E = ND->protocol_end(); I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
+
+ return VisitObjCContainerDecl(ND);
+}
+
+bool CursorVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
+ if (!PID->isThisDeclarationADefinition())
+ return Visit(MakeCursorObjCProtocolRef(PID, PID->getLocation(), TU));
+
+ ObjCProtocolDecl::protocol_loc_iterator PL = PID->protocol_loc_begin();
+ for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
+ E = PID->protocol_end(); I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
+
+ return VisitObjCContainerDecl(PID);
+}
+
+bool CursorVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *PD) {
+ if (PD->getTypeSourceInfo() && Visit(PD->getTypeSourceInfo()->getTypeLoc()))
+ return true;
+
+ // FIXME: This implements a workaround with @property declarations also being
+ // installed in the DeclContext for the @interface. Eventually this code
+ // should be removed.
+ ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(PD->getDeclContext());
+ if (!CDecl || !CDecl->IsClassExtension())
+ return false;
+
+ ObjCInterfaceDecl *ID = CDecl->getClassInterface();
+ if (!ID)
+ return false;
+
+ IdentifierInfo *PropertyId = PD->getIdentifier();
+ ObjCPropertyDecl *prevDecl =
+ ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(ID), PropertyId);
+
+ if (!prevDecl)
+ return false;
+
+ // Visit synthesized methods since they will be skipped when visiting
+ // the @interface.
+ if (ObjCMethodDecl *MD = prevDecl->getGetterMethodDecl())
+ if (MD->isPropertyAccessor() && MD->getLexicalDeclContext() == CDecl)
+ if (Visit(MakeCXCursor(MD, TU, RegionOfInterest)))
+ return true;
+
+ if (ObjCMethodDecl *MD = prevDecl->getSetterMethodDecl())
+ if (MD->isPropertyAccessor() && MD->getLexicalDeclContext() == CDecl)
+ if (Visit(MakeCXCursor(MD, TU, RegionOfInterest)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+ if (!D->isThisDeclarationADefinition()) {
+ // Forward declaration is treated like a reference.
+ return Visit(MakeCursorObjCClassRef(D, D->getLocation(), TU));
+ }
+
+ // Issue callbacks for super class.
+ if (D->getSuperClass() &&
+ Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
+ D->getSuperClassLoc(),
+ TU)))
+ return true;
+
+ ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
+ for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(),
+ E = D->protocol_end(); I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
+
+ return VisitObjCContainerDecl(D);
+}
+
+bool CursorVisitor::VisitObjCImplDecl(ObjCImplDecl *D) {
+ return VisitObjCContainerDecl(D);
+}
+
+bool CursorVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+ // 'ID' could be null when dealing with invalid code.
+ if (ObjCInterfaceDecl *ID = D->getClassInterface())
+ if (Visit(MakeCursorObjCClassRef(ID, D->getLocation(), TU)))
+ return true;
+
+ return VisitObjCImplDecl(D);
+}
+
+bool CursorVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
+#if 0
+ // Issue callbacks for super class.
+ // FIXME: No source location information!
+ if (D->getSuperClass() &&
+ Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
+ D->getSuperClassLoc(),
+ TU)))
+ return true;
+#endif
+
+ return VisitObjCImplDecl(D);
+}
+
+bool CursorVisitor::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD) {
+ if (ObjCIvarDecl *Ivar = PD->getPropertyIvarDecl())
+ if (PD->isIvarNameSpecified())
+ return Visit(MakeCursorMemberRef(Ivar, PD->getPropertyIvarDeclLoc(), TU));
+
+ return false;
+}
+
+bool CursorVisitor::VisitNamespaceDecl(NamespaceDecl *D) {
+ return VisitDeclContext(D);
+}
+
+bool CursorVisitor::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ return Visit(MakeCursorNamespaceRef(D->getAliasedNamespace(),
+ D->getTargetNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitUsingDecl(UsingDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) {
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+ }
+
+ if (Visit(MakeCursorOverloadedDeclRef(D, D->getLocation(), TU)))
+ return true;
+
+ return VisitDeclarationNameInfo(D->getNameInfo());
+}
+
+bool CursorVisitor::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ return Visit(MakeCursorNamespaceRef(D->getNominatedNamespaceAsWritten(),
+ D->getIdentLocation(), TU));
+}
+
+bool CursorVisitor::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) {
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+ }
+
+ return VisitDeclarationNameInfo(D->getNameInfo());
+}
+
+bool CursorVisitor::VisitUnresolvedUsingTypenameDecl(
+ UnresolvedUsingTypenameDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
+ switch (Name.getName().getNameKind()) {
+ case clang::DeclarationName::Identifier:
+ case clang::DeclarationName::CXXLiteralOperatorName:
+ case clang::DeclarationName::CXXOperatorName:
+ case clang::DeclarationName::CXXUsingDirective:
+ return false;
+
+ case clang::DeclarationName::CXXConstructorName:
+ case clang::DeclarationName::CXXDestructorName:
+ case clang::DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TSInfo = Name.getNamedTypeInfo())
+ return Visit(TSInfo->getTypeLoc());
+ return false;
+
+ case clang::DeclarationName::ObjCZeroArgSelector:
+ case clang::DeclarationName::ObjCOneArgSelector:
+ case clang::DeclarationName::ObjCMultiArgSelector:
+ // FIXME: Per-identifier location info?
+ return false;
+ }
+
+ llvm_unreachable("Invalid DeclarationName::Kind!");
+}
+
+bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS,
+ SourceRange Range) {
+ // FIXME: This whole routine is a hack to work around the lack of proper
+ // source information in nested-name-specifiers (PR5791). Since we do have
+ // a beginning source location, we can visit the first component of the
+ // nested-name-specifier, if it's a single-token component.
+ if (!NNS)
+ return false;
+
+ // Get the first component in the nested-name-specifier.
+ while (NestedNameSpecifier *Prefix = NNS->getPrefix())
+ NNS = Prefix;
+
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Namespace:
+ return Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(),
+ TU));
+
+ case NestedNameSpecifier::NamespaceAlias:
+ return Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(),
+ Range.getBegin(), TU));
+
+ case NestedNameSpecifier::TypeSpec: {
+ // If the type has a form where we know that the beginning of the source
+ // range matches up with a reference cursor. Visit the appropriate reference
+ // cursor.
+ const Type *T = NNS->getAsType();
+ if (const TypedefType *Typedef = dyn_cast<TypedefType>(T))
+ return Visit(MakeCursorTypeRef(Typedef->getDecl(), Range.getBegin(), TU));
+ if (const TagType *Tag = dyn_cast<TagType>(T))
+ return Visit(MakeCursorTypeRef(Tag->getDecl(), Range.getBegin(), TU));
+ if (const TemplateSpecializationType *TST
+ = dyn_cast<TemplateSpecializationType>(T))
+ return VisitTemplateName(TST->getTemplateName(), Range.getBegin());
+ break;
+ }
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Identifier:
+ break;
+ }
+
+ return false;
+}
+
+bool
+CursorVisitor::VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) {
+ SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
+ for (; Qualifier; Qualifier = Qualifier.getPrefix())
+ Qualifiers.push_back(Qualifier);
+
+ while (!Qualifiers.empty()) {
+ NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
+ NestedNameSpecifier *NNS = Q.getNestedNameSpecifier();
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Namespace:
+ if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(),
+ Q.getLocalBeginLoc(),
+ TU)))
+ return true;
+
+ break;
+
+ case NestedNameSpecifier::NamespaceAlias:
+ if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(),
+ Q.getLocalBeginLoc(),
+ TU)))
+ return true;
+
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ if (Visit(Q.getTypeLoc()))
+ return true;
+
+ break;
+
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Identifier:
+ break;
+ }
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateParameters(
+ const TemplateParameterList *Params) {
+ if (!Params)
+ return false;
+
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ if (Visit(MakeCXCursor(*P, TU, RegionOfInterest)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
+ switch (Name.getKind()) {
+ case TemplateName::Template:
+ return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU));
+
+ case TemplateName::OverloadedTemplate:
+ // Visit the overloaded template set.
+ if (Visit(MakeCursorOverloadedDeclRef(Name, Loc, TU)))
+ return true;
+
+ return false;
+
+ case TemplateName::DependentTemplate:
+ // FIXME: Visit nested-name-specifier.
+ return false;
+
+ case TemplateName::QualifiedTemplate:
+ // FIXME: Visit nested-name-specifier.
+ return Visit(MakeCursorTemplateRef(
+ Name.getAsQualifiedTemplateName()->getDecl(),
+ Loc, TU));
+
+ case TemplateName::SubstTemplateTemplateParm:
+ return Visit(MakeCursorTemplateRef(
+ Name.getAsSubstTemplateTemplateParm()->getParameter(),
+ Loc, TU));
+
+ case TemplateName::SubstTemplateTemplateParmPack:
+ return Visit(MakeCursorTemplateRef(
+ Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(),
+ Loc, TU));
+ }
+
+ llvm_unreachable("Invalid TemplateName::Kind!");
+}
+
+bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
+ switch (TAL.getArgument().getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ return false;
+
+ case TemplateArgument::Type:
+ if (TypeSourceInfo *TSInfo = TAL.getTypeSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+ return false;
+
+ case TemplateArgument::Declaration:
+ if (Expr *E = TAL.getSourceDeclExpression())
+ return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
+ return false;
+
+ case TemplateArgument::NullPtr:
+ if (Expr *E = TAL.getSourceNullPtrExpression())
+ return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
+ return false;
+
+ case TemplateArgument::Expression:
+ if (Expr *E = TAL.getSourceExpression())
+ return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
+ return false;
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ if (VisitNestedNameSpecifierLoc(TAL.getTemplateQualifierLoc()))
+ return true;
+
+ return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(),
+ TAL.getTemplateNameLoc());
+ }
+
+ llvm_unreachable("Invalid TemplateArgument::Kind!");
+}
+
+bool CursorVisitor::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+ return VisitDeclContext(D);
+}
+
+bool CursorVisitor::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ return Visit(TL.getUnqualifiedLoc());
+}
+
+bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+ ASTContext &Context = AU->getASTContext();
+
+ // Some builtin types (such as Objective-C's "id", "sel", and
+ // "Class") have associated declarations. Create cursors for those.
+ QualType VisitType;
+ switch (TL.getTypePtr()->getKind()) {
+
+ case BuiltinType::Void:
+ case BuiltinType::NullPtr:
+ case BuiltinType::Dependent:
+#define BUILTIN_TYPE(Id, SingletonId)
+#define SIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
+#define UNSIGNED_TYPE(Id, SingletonId) case BuiltinType::Id:
+#define FLOATING_TYPE(Id, SingletonId) case BuiltinType::Id:
+#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
+#include "clang/AST/BuiltinTypes.def"
+ break;
+
+ case BuiltinType::ObjCId:
+ VisitType = Context.getObjCIdType();
+ break;
+
+ case BuiltinType::ObjCClass:
+ VisitType = Context.getObjCClassType();
+ break;
+
+ case BuiltinType::ObjCSel:
+ VisitType = Context.getObjCSelType();
+ break;
+ }
+
+ if (!VisitType.isNull()) {
+ if (const TypedefType *Typedef = VisitType->getAs<TypedefType>())
+ return Visit(MakeCursorTypeRef(Typedef->getDecl(), TL.getBuiltinLoc(),
+ TU));
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getTypedefNameDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
+ if (TL.isDefinition())
+ return Visit(MakeCXCursor(TL.getDecl(), TU, RegionOfInterest));
+
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
+ if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseLoc()))
+ return true;
+
+ for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
+ if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
+ TU)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitParenTypeLoc(ParenTypeLoc TL) {
+ return Visit(TL.getInnerLoc());
+}
+
+bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+ return Visit(TL.getModifiedLoc());
+}
+
+bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL,
+ bool SkipResultType) {
+ if (!SkipResultType && Visit(TL.getResultLoc()))
+ return true;
+
+ for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+ if (Decl *D = TL.getArg(I))
+ if (Visit(MakeCXCursor(D, TU, RegionOfInterest)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {
+ if (Visit(TL.getElementLoc()))
+ return true;
+
+ if (Expr *Size = TL.getSizeExpr())
+ return Visit(MakeCXCursor(Size, StmtParent, TU, RegionOfInterest));
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
+ TemplateSpecializationTypeLoc TL) {
+ // Visit the template name.
+ if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
+ TL.getTemplateNameLoc()))
+ return true;
+
+ // Visit the template arguments.
+ for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+ return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));
+}
+
+bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+ if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
+bool CursorVisitor::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
+ if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
+bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+ if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc(
+ DependentTemplateSpecializationTypeLoc TL) {
+ // Visit the nested-name-specifier, if there is one.
+ if (TL.getQualifierLoc() &&
+ VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
+ // Visit the template arguments.
+ for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+ if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return true;
+
+ return Visit(TL.getNamedTypeLoc());
+}
+
+bool CursorVisitor::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
+ return Visit(TL.getPatternLoc());
+}
+
+bool CursorVisitor::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
+ if (Expr *E = TL.getUnderlyingExpr())
+ return Visit(MakeCXCursor(E, StmtParent, TU));
+
+ return false;
+}
+
+bool CursorVisitor::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
+ return Visit(TL.getValueLoc());
+}
+
+#define DEFAULT_TYPELOC_IMPL(CLASS, PARENT) \
+bool CursorVisitor::Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { \
+ return Visit##PARENT##Loc(TL); \
+}
+
+DEFAULT_TYPELOC_IMPL(Complex, Type)
+DEFAULT_TYPELOC_IMPL(ConstantArray, ArrayType)
+DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType)
+DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType)
+DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType)
+DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type)
+DEFAULT_TYPELOC_IMPL(Vector, Type)
+DEFAULT_TYPELOC_IMPL(ExtVector, VectorType)
+DEFAULT_TYPELOC_IMPL(FunctionProto, FunctionType)
+DEFAULT_TYPELOC_IMPL(FunctionNoProto, FunctionType)
+DEFAULT_TYPELOC_IMPL(Record, TagType)
+DEFAULT_TYPELOC_IMPL(Enum, TagType)
+DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParm, Type)
+DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParmPack, Type)
+DEFAULT_TYPELOC_IMPL(Auto, Type)
+
+bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
+ // Visit the nested-name-specifier, if present.
+ if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ if (D->isCompleteDefinition()) {
+ for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
+ E = D->bases_end(); I != E; ++I) {
+ if (Visit(cxcursor::MakeCursorCXXBaseSpecifier(I, TU)))
+ return true;
+ }
+ }
+
+ return VisitTagDecl(D);
+}
+
+bool CursorVisitor::VisitAttributes(Decl *D) {
+ for (AttrVec::const_iterator i = D->attr_begin(), e = D->attr_end();
+ i != e; ++i)
+ if (Visit(MakeCXCursor(*i, D, TU)))
+ return true;
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Data-recursive visitor methods.
+//===----------------------------------------------------------------------===//
+
+namespace {
+#define DEF_JOB(NAME, DATA, KIND)\
+class NAME : public VisitorJob {\
+public:\
+ NAME(DATA *d, CXCursor parent) : VisitorJob(parent, VisitorJob::KIND, d) {} \
+ static bool classof(const VisitorJob *VJ) { return VJ->getKind() == KIND; }\
+ DATA *get() const { return static_cast<DATA*>(data[0]); }\
+};
+
+DEF_JOB(StmtVisit, Stmt, StmtVisitKind)
+DEF_JOB(MemberExprParts, MemberExpr, MemberExprPartsKind)
+DEF_JOB(DeclRefExprParts, DeclRefExpr, DeclRefExprPartsKind)
+DEF_JOB(OverloadExprParts, OverloadExpr, OverloadExprPartsKind)
+DEF_JOB(ExplicitTemplateArgsVisit, ASTTemplateArgumentListInfo,
+ ExplicitTemplateArgsVisitKind)
+DEF_JOB(SizeOfPackExprParts, SizeOfPackExpr, SizeOfPackExprPartsKind)
+DEF_JOB(LambdaExprParts, LambdaExpr, LambdaExprPartsKind)
+DEF_JOB(PostChildrenVisit, void, PostChildrenVisitKind)
+#undef DEF_JOB
+
+class DeclVisit : public VisitorJob {
+public:
+ DeclVisit(Decl *d, CXCursor parent, bool isFirst) :
+ VisitorJob(parent, VisitorJob::DeclVisitKind,
+ d, isFirst ? (void*) 1 : (void*) 0) {}
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == DeclVisitKind;
+ }
+ Decl *get() const { return static_cast<Decl*>(data[0]); }
+ bool isFirst() const { return data[1] ? true : false; }
+};
+class TypeLocVisit : public VisitorJob {
+public:
+ TypeLocVisit(TypeLoc tl, CXCursor parent) :
+ VisitorJob(parent, VisitorJob::TypeLocVisitKind,
+ tl.getType().getAsOpaquePtr(), tl.getOpaqueData()) {}
+
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == TypeLocVisitKind;
+ }
+
+ TypeLoc get() const {
+ QualType T = QualType::getFromOpaquePtr(data[0]);
+ return TypeLoc(T, data[1]);
+ }
+};
+
+class LabelRefVisit : public VisitorJob {
+public:
+ LabelRefVisit(LabelDecl *LD, SourceLocation labelLoc, CXCursor parent)
+ : VisitorJob(parent, VisitorJob::LabelRefVisitKind, LD,
+ labelLoc.getPtrEncoding()) {}
+
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == VisitorJob::LabelRefVisitKind;
+ }
+ LabelDecl *get() const { return static_cast<LabelDecl*>(data[0]); }
+ SourceLocation getLoc() const {
+ return SourceLocation::getFromPtrEncoding(data[1]); }
+};
+
+class NestedNameSpecifierLocVisit : public VisitorJob {
+public:
+ NestedNameSpecifierLocVisit(NestedNameSpecifierLoc Qualifier, CXCursor parent)
+ : VisitorJob(parent, VisitorJob::NestedNameSpecifierLocVisitKind,
+ Qualifier.getNestedNameSpecifier(),
+ Qualifier.getOpaqueData()) { }
+
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == VisitorJob::NestedNameSpecifierLocVisitKind;
+ }
+
+ NestedNameSpecifierLoc get() const {
+ return NestedNameSpecifierLoc(static_cast<NestedNameSpecifier*>(data[0]),
+ data[1]);
+ }
+};
+
+class DeclarationNameInfoVisit : public VisitorJob {
+public:
+ DeclarationNameInfoVisit(Stmt *S, CXCursor parent)
+ : VisitorJob(parent, VisitorJob::DeclarationNameInfoVisitKind, S) {}
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == VisitorJob::DeclarationNameInfoVisitKind;
+ }
+ DeclarationNameInfo get() const {
+ Stmt *S = static_cast<Stmt*>(data[0]);
+ switch (S->getStmtClass()) {
+ default:
+ llvm_unreachable("Unhandled Stmt");
+ case clang::Stmt::MSDependentExistsStmtClass:
+ return cast<MSDependentExistsStmt>(S)->getNameInfo();
+ case Stmt::CXXDependentScopeMemberExprClass:
+ return cast<CXXDependentScopeMemberExpr>(S)->getMemberNameInfo();
+ case Stmt::DependentScopeDeclRefExprClass:
+ return cast<DependentScopeDeclRefExpr>(S)->getNameInfo();
+ }
+ }
+};
+class MemberRefVisit : public VisitorJob {
+public:
+ MemberRefVisit(FieldDecl *D, SourceLocation L, CXCursor parent)
+ : VisitorJob(parent, VisitorJob::MemberRefVisitKind, D,
+ L.getPtrEncoding()) {}
+ static bool classof(const VisitorJob *VJ) {
+ return VJ->getKind() == VisitorJob::MemberRefVisitKind;
+ }
+ FieldDecl *get() const {
+ return static_cast<FieldDecl*>(data[0]);
+ }
+ SourceLocation getLoc() const {
+ return SourceLocation::getFromRawEncoding((unsigned)(uintptr_t) data[1]);
+ }
+};
+class EnqueueVisitor : public StmtVisitor<EnqueueVisitor, void> {
+ VisitorWorkList &WL;
+ CXCursor Parent;
+public:
+ EnqueueVisitor(VisitorWorkList &wl, CXCursor parent)
+ : WL(wl), Parent(parent) {}
+
+ void VisitAddrLabelExpr(AddrLabelExpr *E);
+ void VisitBlockExpr(BlockExpr *B);
+ void VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
+ void VisitCompoundStmt(CompoundStmt *S);
+ void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { /* Do nothing. */ }
+ void VisitMSDependentExistsStmt(MSDependentExistsStmt *S);
+ void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
+ void VisitCXXNewExpr(CXXNewExpr *E);
+ void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
+ void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
+ void VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
+ void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
+ void VisitCXXTypeidExpr(CXXTypeidExpr *E);
+ void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
+ void VisitCXXUuidofExpr(CXXUuidofExpr *E);
+ void VisitCXXCatchStmt(CXXCatchStmt *S);
+ void VisitDeclRefExpr(DeclRefExpr *D);
+ void VisitDeclStmt(DeclStmt *S);
+ void VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
+ void VisitDesignatedInitExpr(DesignatedInitExpr *E);
+ void VisitExplicitCastExpr(ExplicitCastExpr *E);
+ void VisitForStmt(ForStmt *FS);
+ void VisitGotoStmt(GotoStmt *GS);
+ void VisitIfStmt(IfStmt *If);
+ void VisitInitListExpr(InitListExpr *IE);
+ void VisitMemberExpr(MemberExpr *M);
+ void VisitOffsetOfExpr(OffsetOfExpr *E);
+ void VisitObjCEncodeExpr(ObjCEncodeExpr *E);
+ void VisitObjCMessageExpr(ObjCMessageExpr *M);
+ void VisitOverloadExpr(OverloadExpr *E);
+ void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
+ void VisitStmt(Stmt *S);
+ void VisitSwitchStmt(SwitchStmt *S);
+ void VisitWhileStmt(WhileStmt *W);
+ void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
+ void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
+ void VisitTypeTraitExpr(TypeTraitExpr *E);
+ void VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
+ void VisitExpressionTraitExpr(ExpressionTraitExpr *E);
+ void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U);
+ void VisitVAArgExpr(VAArgExpr *E);
+ void VisitSizeOfPackExpr(SizeOfPackExpr *E);
+ void VisitPseudoObjectExpr(PseudoObjectExpr *E);
+ void VisitOpaqueValueExpr(OpaqueValueExpr *E);
+ void VisitLambdaExpr(LambdaExpr *E);
+
+private:
+ void AddDeclarationNameInfo(Stmt *S);
+ void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
+ void AddExplicitTemplateArgs(const ASTTemplateArgumentListInfo *A);
+ void AddMemberRef(FieldDecl *D, SourceLocation L);
+ void AddStmt(Stmt *S);
+ void AddDecl(Decl *D, bool isFirst = true);
+ void AddTypeLoc(TypeSourceInfo *TI);
+ void EnqueueChildren(Stmt *S);
+};
+} // end anonyous namespace
+
+void EnqueueVisitor::AddDeclarationNameInfo(Stmt *S) {
+ // 'S' should always be non-null, since it comes from the
+ // statement we are visiting.
+ WL.push_back(DeclarationNameInfoVisit(S, Parent));
+}
+
+void
+EnqueueVisitor::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) {
+ if (Qualifier)
+ WL.push_back(NestedNameSpecifierLocVisit(Qualifier, Parent));
+}
+
+void EnqueueVisitor::AddStmt(Stmt *S) {
+ if (S)
+ WL.push_back(StmtVisit(S, Parent));
+}
+void EnqueueVisitor::AddDecl(Decl *D, bool isFirst) {
+ if (D)
+ WL.push_back(DeclVisit(D, Parent, isFirst));
+}
+void EnqueueVisitor::
+ AddExplicitTemplateArgs(const ASTTemplateArgumentListInfo *A) {
+ if (A)
+ WL.push_back(ExplicitTemplateArgsVisit(
+ const_cast<ASTTemplateArgumentListInfo*>(A), Parent));
+}
+void EnqueueVisitor::AddMemberRef(FieldDecl *D, SourceLocation L) {
+ if (D)
+ WL.push_back(MemberRefVisit(D, L, Parent));
+}
+void EnqueueVisitor::AddTypeLoc(TypeSourceInfo *TI) {
+ if (TI)
+ WL.push_back(TypeLocVisit(TI->getTypeLoc(), Parent));
+ }
+void EnqueueVisitor::EnqueueChildren(Stmt *S) {
+ unsigned size = WL.size();
+ for (Stmt::child_range Child = S->children(); Child; ++Child) {
+ AddStmt(*Child);
+ }
+ if (size == WL.size())
+ return;
+ // Now reverse the entries we just added. This will match the DFS
+ // ordering performed by the worklist.
+ VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
+ std::reverse(I, E);
+}
+void EnqueueVisitor::VisitAddrLabelExpr(AddrLabelExpr *E) {
+ WL.push_back(LabelRefVisit(E->getLabel(), E->getLabelLoc(), Parent));
+}
+void EnqueueVisitor::VisitBlockExpr(BlockExpr *B) {
+ AddDecl(B->getBlockDecl());
+}
+void EnqueueVisitor::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ EnqueueChildren(E);
+ AddTypeLoc(E->getTypeSourceInfo());
+}
+void EnqueueVisitor::VisitCompoundStmt(CompoundStmt *S) {
+ for (CompoundStmt::reverse_body_iterator I = S->body_rbegin(),
+ E = S->body_rend(); I != E; ++I) {
+ AddStmt(*I);
+ }
+}
+void EnqueueVisitor::
+VisitMSDependentExistsStmt(MSDependentExistsStmt *S) {
+ AddStmt(S->getSubStmt());
+ AddDeclarationNameInfo(S);
+ if (NestedNameSpecifierLoc QualifierLoc = S->getQualifierLoc())
+ AddNestedNameSpecifierLoc(QualifierLoc);
+}
+
+void EnqueueVisitor::
+VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
+ AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
+ AddDeclarationNameInfo(E);
+ if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
+ AddNestedNameSpecifierLoc(QualifierLoc);
+ if (!E->isImplicitAccess())
+ AddStmt(E->getBase());
+}
+void EnqueueVisitor::VisitCXXNewExpr(CXXNewExpr *E) {
+ // Enqueue the initializer , if any.
+ AddStmt(E->getInitializer());
+ // Enqueue the array size, if any.
+ AddStmt(E->getArraySize());
+ // Enqueue the allocated type.
+ AddTypeLoc(E->getAllocatedTypeSourceInfo());
+ // Enqueue the placement arguments.
+ for (unsigned I = E->getNumPlacementArgs(); I > 0; --I)
+ AddStmt(E->getPlacementArg(I-1));
+}
+void EnqueueVisitor::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
+ for (unsigned I = CE->getNumArgs(); I > 1 /* Yes, this is 1 */; --I)
+ AddStmt(CE->getArg(I-1));
+ AddStmt(CE->getCallee());
+ AddStmt(CE->getArg(0));
+}
+void EnqueueVisitor::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
+ // Visit the name of the type being destroyed.
+ AddTypeLoc(E->getDestroyedTypeInfo());
+ // Visit the scope type that looks disturbingly like the nested-name-specifier
+ // but isn't.
+ AddTypeLoc(E->getScopeTypeInfo());
+ // Visit the nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
+ AddNestedNameSpecifierLoc(QualifierLoc);
+ // Visit base expression.
+ AddStmt(E->getBase());
+}
+void EnqueueVisitor::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+ AddTypeLoc(E->getTypeSourceInfo());
+}
+void EnqueueVisitor::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
+ EnqueueChildren(E);
+ AddTypeLoc(E->getTypeSourceInfo());
+}
+void EnqueueVisitor::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+ EnqueueChildren(E);
+ if (E->isTypeOperand())
+ AddTypeLoc(E->getTypeOperandSourceInfo());
+}
+
+void EnqueueVisitor::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr
+ *E) {
+ EnqueueChildren(E);
+ AddTypeLoc(E->getTypeSourceInfo());
+}
+void EnqueueVisitor::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
+ EnqueueChildren(E);
+ if (E->isTypeOperand())
+ AddTypeLoc(E->getTypeOperandSourceInfo());
+}
+
+void EnqueueVisitor::VisitCXXCatchStmt(CXXCatchStmt *S) {
+ EnqueueChildren(S);
+ AddDecl(S->getExceptionDecl());
+}
+
+void EnqueueVisitor::VisitDeclRefExpr(DeclRefExpr *DR) {
+ if (DR->hasExplicitTemplateArgs()) {
+ AddExplicitTemplateArgs(&DR->getExplicitTemplateArgs());
+ }
+ WL.push_back(DeclRefExprParts(DR, Parent));
+}
+void EnqueueVisitor::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
+ AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
+ AddDeclarationNameInfo(E);
+ AddNestedNameSpecifierLoc(E->getQualifierLoc());
+}
+void EnqueueVisitor::VisitDeclStmt(DeclStmt *S) {
+ unsigned size = WL.size();
+ bool isFirst = true;
+ for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+ D != DEnd; ++D) {
+ AddDecl(*D, isFirst);
+ isFirst = false;
+ }
+ if (size == WL.size())
+ return;
+ // Now reverse the entries we just added. This will match the DFS
+ // ordering performed by the worklist.
+ VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
+ std::reverse(I, E);
+}
+void EnqueueVisitor::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+ AddStmt(E->getInit());
+ typedef DesignatedInitExpr::Designator Designator;
+ for (DesignatedInitExpr::reverse_designators_iterator
+ D = E->designators_rbegin(), DEnd = E->designators_rend();
+ D != DEnd; ++D) {
+ if (D->isFieldDesignator()) {
+ if (FieldDecl *Field = D->getField())
+ AddMemberRef(Field, D->getFieldLoc());
+ continue;
+ }
+ if (D->isArrayDesignator()) {
+ AddStmt(E->getArrayIndex(*D));
+ continue;
+ }
+ assert(D->isArrayRangeDesignator() && "Unknown designator kind");
+ AddStmt(E->getArrayRangeEnd(*D));
+ AddStmt(E->getArrayRangeStart(*D));
+ }
+}
+void EnqueueVisitor::VisitExplicitCastExpr(ExplicitCastExpr *E) {
+ EnqueueChildren(E);
+ AddTypeLoc(E->getTypeInfoAsWritten());
+}
+void EnqueueVisitor::VisitForStmt(ForStmt *FS) {
+ AddStmt(FS->getBody());
+ AddStmt(FS->getInc());
+ AddStmt(FS->getCond());
+ AddDecl(FS->getConditionVariable());
+ AddStmt(FS->getInit());
+}
+void EnqueueVisitor::VisitGotoStmt(GotoStmt *GS) {
+ WL.push_back(LabelRefVisit(GS->getLabel(), GS->getLabelLoc(), Parent));
+}
+void EnqueueVisitor::VisitIfStmt(IfStmt *If) {
+ AddStmt(If->getElse());
+ AddStmt(If->getThen());
+ AddStmt(If->getCond());
+ AddDecl(If->getConditionVariable());
+}
+void EnqueueVisitor::VisitInitListExpr(InitListExpr *IE) {
+ // We care about the syntactic form of the initializer list, only.
+ if (InitListExpr *Syntactic = IE->getSyntacticForm())
+ IE = Syntactic;
+ EnqueueChildren(IE);
+}
+void EnqueueVisitor::VisitMemberExpr(MemberExpr *M) {
+ WL.push_back(MemberExprParts(M, Parent));
+
+ // If the base of the member access expression is an implicit 'this', don't
+ // visit it.
+ // FIXME: If we ever want to show these implicit accesses, this will be
+ // unfortunate. However, clang_getCursor() relies on this behavior.
+ if (!M->isImplicitAccess())
+ AddStmt(M->getBase());
+}
+void EnqueueVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
+ AddTypeLoc(E->getEncodedTypeSourceInfo());
+}
+void EnqueueVisitor::VisitObjCMessageExpr(ObjCMessageExpr *M) {
+ EnqueueChildren(M);
+ AddTypeLoc(M->getClassReceiverTypeInfo());
+}
+void EnqueueVisitor::VisitOffsetOfExpr(OffsetOfExpr *E) {
+ // Visit the components of the offsetof expression.
+ for (unsigned N = E->getNumComponents(), I = N; I > 0; --I) {
+ typedef OffsetOfExpr::OffsetOfNode OffsetOfNode;
+ const OffsetOfNode &Node = E->getComponent(I-1);
+ switch (Node.getKind()) {
+ case OffsetOfNode::Array:
+ AddStmt(E->getIndexExpr(Node.getArrayExprIndex()));
+ break;
+ case OffsetOfNode::Field:
+ AddMemberRef(Node.getField(), Node.getSourceRange().getEnd());
+ break;
+ case OffsetOfNode::Identifier:
+ case OffsetOfNode::Base:
+ continue;
+ }
+ }
+ // Visit the type into which we're computing the offset.
+ AddTypeLoc(E->getTypeSourceInfo());
+}
+void EnqueueVisitor::VisitOverloadExpr(OverloadExpr *E) {
+ AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
+ WL.push_back(OverloadExprParts(E, Parent));
+}
+void EnqueueVisitor::VisitUnaryExprOrTypeTraitExpr(
+ UnaryExprOrTypeTraitExpr *E) {
+ EnqueueChildren(E);
+ if (E->isArgumentType())
+ AddTypeLoc(E->getArgumentTypeInfo());
+}
+void EnqueueVisitor::VisitStmt(Stmt *S) {
+ EnqueueChildren(S);
+}
+void EnqueueVisitor::VisitSwitchStmt(SwitchStmt *S) {
+ AddStmt(S->getBody());
+ AddStmt(S->getCond());
+ AddDecl(S->getConditionVariable());
+}
+
+void EnqueueVisitor::VisitWhileStmt(WhileStmt *W) {
+ AddStmt(W->getBody());
+ AddStmt(W->getCond());
+ AddDecl(W->getConditionVariable());
+}
+
+void EnqueueVisitor::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
+ AddTypeLoc(E->getQueriedTypeSourceInfo());
+}
+
+void EnqueueVisitor::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+ AddTypeLoc(E->getRhsTypeSourceInfo());
+ AddTypeLoc(E->getLhsTypeSourceInfo());
+}
+
+void EnqueueVisitor::VisitTypeTraitExpr(TypeTraitExpr *E) {
+ for (unsigned I = E->getNumArgs(); I > 0; --I)
+ AddTypeLoc(E->getArg(I-1));
+}
+
+void EnqueueVisitor::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
+ AddTypeLoc(E->getQueriedTypeSourceInfo());
+}
+
+void EnqueueVisitor::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
+ EnqueueChildren(E);
+}
+
+void EnqueueVisitor::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U) {
+ VisitOverloadExpr(U);
+ if (!U->isImplicitAccess())
+ AddStmt(U->getBase());
+}
+void EnqueueVisitor::VisitVAArgExpr(VAArgExpr *E) {
+ AddStmt(E->getSubExpr());
+ AddTypeLoc(E->getWrittenTypeInfo());
+}
+void EnqueueVisitor::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
+ WL.push_back(SizeOfPackExprParts(E, Parent));
+}
+void EnqueueVisitor::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+ // If the opaque value has a source expression, just transparently
+ // visit that. This is useful for (e.g.) pseudo-object expressions.
+ if (Expr *SourceExpr = E->getSourceExpr())
+ return Visit(SourceExpr);
+}
+void EnqueueVisitor::VisitLambdaExpr(LambdaExpr *E) {
+ AddStmt(E->getBody());
+ WL.push_back(LambdaExprParts(E, Parent));
+}
+void EnqueueVisitor::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
+ // Treat the expression like its syntactic form.
+ Visit(E->getSyntacticForm());
+}
+
+void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, Stmt *S) {
+ EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S);
+}
+
+bool CursorVisitor::IsInRegionOfInterest(CXCursor C) {
+ if (RegionOfInterest.isValid()) {
+ SourceRange Range = getRawCursorExtent(C);
+ if (Range.isInvalid() || CompareRegionOfInterest(Range))
+ return false;
+ }
+ return true;
+}
+
+bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
+ while (!WL.empty()) {
+ // Dequeue the worklist item.
+ VisitorJob LI = WL.back();
+ WL.pop_back();
+
+ // Set the Parent field, then back to its old value once we're done.
+ SetParentRAII SetParent(Parent, StmtParent, LI.getParent());
+
+ switch (LI.getKind()) {
+ case VisitorJob::DeclVisitKind: {
+ Decl *D = cast<DeclVisit>(&LI)->get();
+ if (!D)
+ continue;
+
+ // For now, perform default visitation for Decls.
+ if (Visit(MakeCXCursor(D, TU, RegionOfInterest,
+ cast<DeclVisit>(&LI)->isFirst())))
+ return true;
+
+ continue;
+ }
+ case VisitorJob::ExplicitTemplateArgsVisitKind: {
+ const ASTTemplateArgumentListInfo *ArgList =
+ cast<ExplicitTemplateArgsVisit>(&LI)->get();
+ for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(),
+ *ArgEnd = Arg + ArgList->NumTemplateArgs;
+ Arg != ArgEnd; ++Arg) {
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+ continue;
+ }
+ case VisitorJob::TypeLocVisitKind: {
+ // Perform default visitation for TypeLocs.
+ if (Visit(cast<TypeLocVisit>(&LI)->get()))
+ return true;
+ continue;
+ }
+ case VisitorJob::LabelRefVisitKind: {
+ LabelDecl *LS = cast<LabelRefVisit>(&LI)->get();
+ if (LabelStmt *stmt = LS->getStmt()) {
+ if (Visit(MakeCursorLabelRef(stmt, cast<LabelRefVisit>(&LI)->getLoc(),
+ TU))) {
+ return true;
+ }
+ }
+ continue;
+ }
+
+ case VisitorJob::NestedNameSpecifierLocVisitKind: {
+ NestedNameSpecifierLocVisit *V = cast<NestedNameSpecifierLocVisit>(&LI);
+ if (VisitNestedNameSpecifierLoc(V->get()))
+ return true;
+ continue;
+ }
+
+ case VisitorJob::DeclarationNameInfoVisitKind: {
+ if (VisitDeclarationNameInfo(cast<DeclarationNameInfoVisit>(&LI)
+ ->get()))
+ return true;
+ continue;
+ }
+ case VisitorJob::MemberRefVisitKind: {
+ MemberRefVisit *V = cast<MemberRefVisit>(&LI);
+ if (Visit(MakeCursorMemberRef(V->get(), V->getLoc(), TU)))
+ return true;
+ continue;
+ }
+ case VisitorJob::StmtVisitKind: {
+ Stmt *S = cast<StmtVisit>(&LI)->get();
+ if (!S)
+ continue;
+
+ // Update the current cursor.
+ CXCursor Cursor = MakeCXCursor(S, StmtParent, TU, RegionOfInterest);
+ if (!IsInRegionOfInterest(Cursor))
+ continue;
+ switch (Visitor(Cursor, Parent, ClientData)) {
+ case CXChildVisit_Break: return true;
+ case CXChildVisit_Continue: break;
+ case CXChildVisit_Recurse:
+ if (PostChildrenVisitor)
+ WL.push_back(PostChildrenVisit(0, Cursor));
+ EnqueueWorkList(WL, S);
+ break;
+ }
+ continue;
+ }
+ case VisitorJob::MemberExprPartsKind: {
+ // Handle the other pieces in the MemberExpr besides the base.
+ MemberExpr *M = cast<MemberExprParts>(&LI)->get();
+
+ // Visit the nested-name-specifier
+ if (NestedNameSpecifierLoc QualifierLoc = M->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(M->getMemberNameInfo()))
+ return true;
+
+ // Visit the explicitly-specified template arguments, if any.
+ if (M->hasExplicitTemplateArgs()) {
+ for (const TemplateArgumentLoc *Arg = M->getTemplateArgs(),
+ *ArgEnd = Arg + M->getNumTemplateArgs();
+ Arg != ArgEnd; ++Arg) {
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+ }
+ continue;
+ }
+ case VisitorJob::DeclRefExprPartsKind: {
+ DeclRefExpr *DR = cast<DeclRefExprParts>(&LI)->get();
+ // Visit nested-name-specifier, if present.
+ if (NestedNameSpecifierLoc QualifierLoc = DR->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+ // Visit declaration name.
+ if (VisitDeclarationNameInfo(DR->getNameInfo()))
+ return true;
+ continue;
+ }
+ case VisitorJob::OverloadExprPartsKind: {
+ OverloadExpr *O = cast<OverloadExprParts>(&LI)->get();
+ // Visit the nested-name-specifier.
+ if (NestedNameSpecifierLoc QualifierLoc = O->getQualifierLoc())
+ if (VisitNestedNameSpecifierLoc(QualifierLoc))
+ return true;
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(O->getNameInfo()))
+ return true;
+ // Visit the overloaded declaration reference.
+ if (Visit(MakeCursorOverloadedDeclRef(O, TU)))
+ return true;
+ continue;
+ }
+ case VisitorJob::SizeOfPackExprPartsKind: {
+ SizeOfPackExpr *E = cast<SizeOfPackExprParts>(&LI)->get();
+ NamedDecl *Pack = E->getPack();
+ if (isa<TemplateTypeParmDecl>(Pack)) {
+ if (Visit(MakeCursorTypeRef(cast<TemplateTypeParmDecl>(Pack),
+ E->getPackLoc(), TU)))
+ return true;
+
+ continue;
+ }
+
+ if (isa<TemplateTemplateParmDecl>(Pack)) {
+ if (Visit(MakeCursorTemplateRef(cast<TemplateTemplateParmDecl>(Pack),
+ E->getPackLoc(), TU)))
+ return true;
+
+ continue;
+ }
+
+ // Non-type template parameter packs and function parameter packs are
+ // treated like DeclRefExpr cursors.
+ continue;
+ }
+
+ case VisitorJob::LambdaExprPartsKind: {
+ // Visit captures.
+ LambdaExpr *E = cast<LambdaExprParts>(&LI)->get();
+ for (LambdaExpr::capture_iterator C = E->explicit_capture_begin(),
+ CEnd = E->explicit_capture_end();
+ C != CEnd; ++C) {
+ if (C->capturesThis())
+ continue;
+
+ if (Visit(MakeCursorVariableRef(C->getCapturedVar(),
+ C->getLocation(),
+ TU)))
+ return true;
+ }
+
+ // Visit parameters and return type, if present.
+ if (E->hasExplicitParameters() || E->hasExplicitResultType()) {
+ TypeLoc TL = E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+ if (E->hasExplicitParameters() && E->hasExplicitResultType()) {
+ // Visit the whole type.
+ if (Visit(TL))
+ return true;
+ } else if (isa<FunctionProtoTypeLoc>(TL)) {
+ FunctionProtoTypeLoc Proto = cast<FunctionProtoTypeLoc>(TL);
+ if (E->hasExplicitParameters()) {
+ // Visit parameters.
+ for (unsigned I = 0, N = Proto.getNumArgs(); I != N; ++I)
+ if (Visit(MakeCXCursor(Proto.getArg(I), TU)))
+ return true;
+ } else {
+ // Visit result type.
+ if (Visit(Proto.getResultLoc()))
+ return true;
+ }
+ }
+ }
+ break;
+ }
+
+ case VisitorJob::PostChildrenVisitKind:
+ if (PostChildrenVisitor(Parent, ClientData))
+ return true;
+ break;
+ }
+ }
+ return false;
+}
+
+bool CursorVisitor::Visit(Stmt *S) {
+ VisitorWorkList *WL = 0;
+ if (!WorkListFreeList.empty()) {
+ WL = WorkListFreeList.back();
+ WL->clear();
+ WorkListFreeList.pop_back();
+ }
+ else {
+ WL = new VisitorWorkList();
+ WorkListCache.push_back(WL);
+ }
+ EnqueueWorkList(*WL, S);
+ bool result = RunVisitorWorkList(*WL);
+ WorkListFreeList.push_back(WL);
+ return result;
+}
+
+namespace {
+typedef llvm::SmallVector<SourceRange, 4> RefNamePieces;
+RefNamePieces buildPieces(unsigned NameFlags, bool IsMemberRefExpr,
+ const DeclarationNameInfo &NI,
+ const SourceRange &QLoc,
+ const ASTTemplateArgumentListInfo *TemplateArgs = 0){
+ const bool WantQualifier = NameFlags & CXNameRange_WantQualifier;
+ const bool WantTemplateArgs = NameFlags & CXNameRange_WantTemplateArgs;
+ const bool WantSinglePiece = NameFlags & CXNameRange_WantSinglePiece;
+
+ const DeclarationName::NameKind Kind = NI.getName().getNameKind();
+
+ RefNamePieces Pieces;
+
+ if (WantQualifier && QLoc.isValid())
+ Pieces.push_back(QLoc);
+
+ if (Kind != DeclarationName::CXXOperatorName || IsMemberRefExpr)
+ Pieces.push_back(NI.getLoc());
+
+ if (WantTemplateArgs && TemplateArgs)
+ Pieces.push_back(SourceRange(TemplateArgs->LAngleLoc,
+ TemplateArgs->RAngleLoc));
+
+ if (Kind == DeclarationName::CXXOperatorName) {
+ Pieces.push_back(SourceLocation::getFromRawEncoding(
+ NI.getInfo().CXXOperatorName.BeginOpNameLoc));
+ Pieces.push_back(SourceLocation::getFromRawEncoding(
+ NI.getInfo().CXXOperatorName.EndOpNameLoc));
+ }
+
+ if (WantSinglePiece) {
+ SourceRange R(Pieces.front().getBegin(), Pieces.back().getEnd());
+ Pieces.clear();
+ Pieces.push_back(R);
+ }
+
+ return Pieces;
+}
+}
+
+//===----------------------------------------------------------------------===//
+// Misc. API hooks.
+//===----------------------------------------------------------------------===//
+
+static llvm::sys::Mutex EnableMultithreadingMutex;
+static bool EnabledMultithreading;
+
+static void fatal_error_handler(void *user_data, const std::string& reason) {
+ // Write the result out to stderr avoiding errs() because raw_ostreams can
+ // call report_fatal_error.
+ fprintf(stderr, "LIBCLANG FATAL ERROR: %s\n", reason.c_str());
+ ::abort();
+}
+
+extern "C" {
+CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
+ int displayDiagnostics) {
+ // Disable pretty stack trace functionality, which will otherwise be a very
+ // poor citizen of the world and set up all sorts of signal handlers.
+ llvm::DisablePrettyStackTrace = true;
+
+ // We use crash recovery to make some of our APIs more reliable, implicitly
+ // enable it.
+ llvm::CrashRecoveryContext::Enable();
+
+ // Enable support for multithreading in LLVM.
+ {
+ llvm::sys::ScopedLock L(EnableMultithreadingMutex);
+ if (!EnabledMultithreading) {
+ llvm::install_fatal_error_handler(fatal_error_handler, 0);
+ llvm::llvm_start_multithreaded();
+ EnabledMultithreading = true;
+ }
+ }
+
+ CIndexer *CIdxr = new CIndexer();
+ if (excludeDeclarationsFromPCH)
+ CIdxr->setOnlyLocalDecls();
+ if (displayDiagnostics)
+ CIdxr->setDisplayDiagnostics();
+
+ if (getenv("LIBCLANG_BGPRIO_INDEX"))
+ CIdxr->setCXGlobalOptFlags(CIdxr->getCXGlobalOptFlags() |
+ CXGlobalOpt_ThreadBackgroundPriorityForIndexing);
+ if (getenv("LIBCLANG_BGPRIO_EDIT"))
+ CIdxr->setCXGlobalOptFlags(CIdxr->getCXGlobalOptFlags() |
+ CXGlobalOpt_ThreadBackgroundPriorityForEditing);
+
+ return CIdxr;
+}
+
+void clang_disposeIndex(CXIndex CIdx) {
+ if (CIdx)
+ delete static_cast<CIndexer *>(CIdx);
+}
+
+void clang_CXIndex_setGlobalOptions(CXIndex CIdx, unsigned options) {
+ if (CIdx)
+ static_cast<CIndexer *>(CIdx)->setCXGlobalOptFlags(options);
+}
+
+unsigned clang_CXIndex_getGlobalOptions(CXIndex CIdx) {
+ if (CIdx)
+ return static_cast<CIndexer *>(CIdx)->getCXGlobalOptFlags();
+ return 0;
+}
+
+void clang_toggleCrashRecovery(unsigned isEnabled) {
+ if (isEnabled)
+ llvm::CrashRecoveryContext::Enable();
+ else
+ llvm::CrashRecoveryContext::Disable();
+}
+
+CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
+ const char *ast_filename) {
+ if (!CIdx)
+ return 0;
+
+ CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+ FileSystemOptions FileSystemOpts;
+
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
+ ASTUnit *TU = ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts,
+ CXXIdx->getOnlyLocalDecls(),
+ 0, 0,
+ /*CaptureDiagnostics=*/true,
+ /*AllowPCHWithCompilerErrors=*/true,
+ /*UserFilesAreVolatile=*/true);
+ return MakeCXTranslationUnit(CXXIdx, TU);
+}
+
+unsigned clang_defaultEditingTranslationUnitOptions() {
+ return CXTranslationUnit_PrecompiledPreamble |
+ CXTranslationUnit_CacheCompletionResults;
+}
+
+CXTranslationUnit
+clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
+ const char *source_filename,
+ int num_command_line_args,
+ const char * const *command_line_args,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files) {
+ unsigned Options = CXTranslationUnit_DetailedPreprocessingRecord;
+ return clang_parseTranslationUnit(CIdx, source_filename,
+ command_line_args, num_command_line_args,
+ unsaved_files, num_unsaved_files,
+ Options);
+}
+
+struct ParseTranslationUnitInfo {
+ CXIndex CIdx;
+ const char *source_filename;
+ const char *const *command_line_args;
+ int num_command_line_args;
+ struct CXUnsavedFile *unsaved_files;
+ unsigned num_unsaved_files;
+ unsigned options;
+ CXTranslationUnit result;
+};
+static void clang_parseTranslationUnit_Impl(void *UserData) {
+ ParseTranslationUnitInfo *PTUI =
+ static_cast<ParseTranslationUnitInfo*>(UserData);
+ CXIndex CIdx = PTUI->CIdx;
+ const char *source_filename = PTUI->source_filename;
+ const char * const *command_line_args = PTUI->command_line_args;
+ int num_command_line_args = PTUI->num_command_line_args;
+ struct CXUnsavedFile *unsaved_files = PTUI->unsaved_files;
+ unsigned num_unsaved_files = PTUI->num_unsaved_files;
+ unsigned options = PTUI->options;
+ PTUI->result = 0;
+
+ if (!CIdx)
+ return;
+
+ CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+
+ if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
+ setThreadBackgroundPriority();
+
+ bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble;
+ // FIXME: Add a flag for modules.
+ TranslationUnitKind TUKind
+ = (options & CXTranslationUnit_Incomplete)? TU_Prefix : TU_Complete;
+ bool CacheCodeCompetionResults
+ = options & CXTranslationUnit_CacheCompletionResults;
+ bool IncludeBriefCommentsInCodeCompletion
+ = options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
+ bool SkipFunctionBodies = options & CXTranslationUnit_SkipFunctionBodies;
+ bool ForSerialization = options & CXTranslationUnit_ForSerialization;
+
+ // Configure the diagnostics.
+ IntrusiveRefCntPtr<DiagnosticsEngine>
+ Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions,
+ num_command_line_args,
+ command_line_args));
+
+ // Recover resources if we crash before exiting this function.
+ llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
+ llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
+ DiagCleanup(Diags.getPtr());
+
+ OwningPtr<std::vector<ASTUnit::RemappedFile> >
+ RemappedFiles(new std::vector<ASTUnit::RemappedFile>());
+
+ // Recover resources if we crash before exiting this function.
+ llvm::CrashRecoveryContextCleanupRegistrar<
+ std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());
+
+ for (unsigned I = 0; I != num_unsaved_files; ++I) {
+ StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
+ const llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
+ RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename,
+ Buffer));
+ }
+
+ OwningPtr<std::vector<const char *> >
+ Args(new std::vector<const char*>());
+
+ // Recover resources if we crash before exiting this method.
+ llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> >
+ ArgsCleanup(Args.get());
+
+ // Since the Clang C library is primarily used by batch tools dealing with
+ // (often very broken) source code, where spell-checking can have a
+ // significant negative impact on performance (particularly when
+ // precompiled headers are involved), we disable it by default.
+ // Only do this if we haven't found a spell-checking-related argument.
+ bool FoundSpellCheckingArgument = false;
+ for (int I = 0; I != num_command_line_args; ++I) {
+ if (strcmp(command_line_args[I], "-fno-spell-checking") == 0 ||
+ strcmp(command_line_args[I], "-fspell-checking") == 0) {
+ FoundSpellCheckingArgument = true;
+ break;
+ }
+ }
+ if (!FoundSpellCheckingArgument)
+ Args->push_back("-fno-spell-checking");
+
+ Args->insert(Args->end(), command_line_args,
+ command_line_args + num_command_line_args);
+
+ // The 'source_filename' argument is optional. If the caller does not
+ // specify it then it is assumed that the source file is specified
+ // in the actual argument list.
+ // Put the source file after command_line_args otherwise if '-x' flag is
+ // present it will be unused.
+ if (source_filename)
+ Args->push_back(source_filename);
+
+ // Do we need the detailed preprocessing record?
+ if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
+ Args->push_back("-Xclang");
+ Args->push_back("-detailed-preprocessing-record");
+ }
+
+ unsigned NumErrors = Diags->getClient()->getNumErrors();
+ OwningPtr<ASTUnit> ErrUnit;
+ OwningPtr<ASTUnit> Unit(
+ ASTUnit::LoadFromCommandLine(Args->size() ? &(*Args)[0] : 0
+ /* vector::data() not portable */,
+ Args->size() ? (&(*Args)[0] + Args->size()) :0,
+ Diags,
+ CXXIdx->getClangResourcesPath(),
+ CXXIdx->getOnlyLocalDecls(),
+ /*CaptureDiagnostics=*/true,
+ RemappedFiles->size() ? &(*RemappedFiles)[0]:0,
+ RemappedFiles->size(),
+ /*RemappedFilesKeepOriginalName=*/true,
+ PrecompilePreamble,
+ TUKind,
+ CacheCodeCompetionResults,
+ IncludeBriefCommentsInCodeCompletion,
+ /*AllowPCHWithCompilerErrors=*/true,
+ SkipFunctionBodies,
+ /*UserFilesAreVolatile=*/true,
+ ForSerialization,
+ &ErrUnit));
+
+ if (NumErrors != Diags->getClient()->getNumErrors()) {
+ // Make sure to check that 'Unit' is non-NULL.
+ if (CXXIdx->getDisplayDiagnostics())
+ printDiagsToStderr(Unit ? Unit.get() : ErrUnit.get());
+ }
+
+ PTUI->result = MakeCXTranslationUnit(CXXIdx, Unit.take());
+}
+CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,
+ const char *source_filename,
+ const char * const *command_line_args,
+ int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files,
+ unsigned options) {
+ ParseTranslationUnitInfo PTUI = { CIdx, source_filename, command_line_args,
+ num_command_line_args, unsaved_files,
+ num_unsaved_files, options, 0 };
+ llvm::CrashRecoveryContext CRC;
+
+ if (!RunSafely(CRC, clang_parseTranslationUnit_Impl, &PTUI)) {
+ fprintf(stderr, "libclang: crash detected during parsing: {\n");
+ fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
+ fprintf(stderr, " 'command_line_args' : [");
+ for (int i = 0; i != num_command_line_args; ++i) {
+ if (i)
+ fprintf(stderr, ", ");
+ fprintf(stderr, "'%s'", command_line_args[i]);
+ }
+ fprintf(stderr, "],\n");
+ fprintf(stderr, " 'unsaved_files' : [");
+ for (unsigned i = 0; i != num_unsaved_files; ++i) {
+ if (i)
+ fprintf(stderr, ", ");
+ fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
+ unsaved_files[i].Length);
+ }
+ fprintf(stderr, "],\n");
+ fprintf(stderr, " 'options' : %d,\n", options);
+ fprintf(stderr, "}\n");
+
+ return 0;
+ } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
+ PrintLibclangResourceUsage(PTUI.result);
+ }
+
+ return PTUI.result;
+}
+
+unsigned clang_defaultSaveOptions(CXTranslationUnit TU) {
+ return CXSaveTranslationUnit_None;
+}
+
+namespace {
+
+struct SaveTranslationUnitInfo {
+ CXTranslationUnit TU;
+ const char *FileName;
+ unsigned options;
+ CXSaveError result;
+};
+
+}
+
+static void clang_saveTranslationUnit_Impl(void *UserData) {
+ SaveTranslationUnitInfo *STUI =
+ static_cast<SaveTranslationUnitInfo*>(UserData);
+
+ CIndexer *CXXIdx = (CIndexer*)STUI->TU->CIdx;
+ if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
+ setThreadBackgroundPriority();
+
+ bool hadError = static_cast<ASTUnit *>(STUI->TU->TUData)->Save(STUI->FileName);
+ STUI->result = hadError ? CXSaveError_Unknown : CXSaveError_None;
+}
+
+int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
+ unsigned options) {
+ if (!TU)
+ return CXSaveError_InvalidTU;
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+ if (!CXXUnit->hasSema())
+ return CXSaveError_InvalidTU;
+
+ SaveTranslationUnitInfo STUI = { TU, FileName, options, CXSaveError_None };
+
+ if (!CXXUnit->getDiagnostics().hasUnrecoverableErrorOccurred() ||
+ getenv("LIBCLANG_NOTHREADS")) {
+ clang_saveTranslationUnit_Impl(&STUI);
+
+ if (getenv("LIBCLANG_RESOURCE_USAGE"))
+ PrintLibclangResourceUsage(TU);
+
+ return STUI.result;
+ }
+
+ // We have an AST that has invalid nodes due to compiler errors.
+ // Use a crash recovery thread for protection.
+
+ llvm::CrashRecoveryContext CRC;
+
+ if (!RunSafely(CRC, clang_saveTranslationUnit_Impl, &STUI)) {
+ fprintf(stderr, "libclang: crash detected during AST saving: {\n");
+ fprintf(stderr, " 'filename' : '%s'\n", FileName);
+ fprintf(stderr, " 'options' : %d,\n", options);
+ fprintf(stderr, "}\n");
+
+ return CXSaveError_Unknown;
+
+ } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
+ PrintLibclangResourceUsage(TU);
+ }
+
+ return STUI.result;
+}
+
+void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {
+ if (CTUnit) {
+ // If the translation unit has been marked as unsafe to free, just discard
+ // it.
+ if (static_cast<ASTUnit *>(CTUnit->TUData)->isUnsafeToFree())
+ return;
+
+ delete static_cast<ASTUnit *>(CTUnit->TUData);
+ disposeCXStringPool(CTUnit->StringPool);
+ delete static_cast<CXDiagnosticSetImpl *>(CTUnit->Diagnostics);
+ disposeOverridenCXCursorsPool(CTUnit->OverridenCursorsPool);
+ delete CTUnit;
+ }
+}
+
+unsigned clang_defaultReparseOptions(CXTranslationUnit TU) {
+ return CXReparse_None;
+}
+
+struct ReparseTranslationUnitInfo {
+ CXTranslationUnit TU;
+ unsigned num_unsaved_files;
+ struct CXUnsavedFile *unsaved_files;
+ unsigned options;
+ int result;
+};
+
+static void clang_reparseTranslationUnit_Impl(void *UserData) {
+ ReparseTranslationUnitInfo *RTUI =
+ static_cast<ReparseTranslationUnitInfo*>(UserData);
+ CXTranslationUnit TU = RTUI->TU;
+
+ // Reset the associated diagnostics.
+ delete static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
+ TU->Diagnostics = 0;
+
+ unsigned num_unsaved_files = RTUI->num_unsaved_files;
+ struct CXUnsavedFile *unsaved_files = RTUI->unsaved_files;
+ unsigned options = RTUI->options;
+ (void) options;
+ RTUI->result = 1;
+
+ if (!TU)
+ return;
+
+ CIndexer *CXXIdx = (CIndexer*)TU->CIdx;
+ if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
+ setThreadBackgroundPriority();
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ OwningPtr<std::vector<ASTUnit::RemappedFile> >
+ RemappedFiles(new std::vector<ASTUnit::RemappedFile>());
+
+ // Recover resources if we crash before exiting this function.
+ llvm::CrashRecoveryContextCleanupRegistrar<
+ std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get());
+
+ for (unsigned I = 0; I != num_unsaved_files; ++I) {
+ StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
+ const llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
+ RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename,
+ Buffer));
+ }
+
+ if (!CXXUnit->Reparse(RemappedFiles->size() ? &(*RemappedFiles)[0] : 0,
+ RemappedFiles->size()))
+ RTUI->result = 0;
+}
+
+int clang_reparseTranslationUnit(CXTranslationUnit TU,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned options) {
+ ReparseTranslationUnitInfo RTUI = { TU, num_unsaved_files, unsaved_files,
+ options, 0 };
+
+ if (getenv("LIBCLANG_NOTHREADS")) {
+ clang_reparseTranslationUnit_Impl(&RTUI);
+ return RTUI.result;
+ }
+
+ llvm::CrashRecoveryContext CRC;
+
+ if (!RunSafely(CRC, clang_reparseTranslationUnit_Impl, &RTUI)) {
+ fprintf(stderr, "libclang: crash detected during reparsing\n");
+ static_cast<ASTUnit *>(TU->TUData)->setUnsafeToFree(true);
+ return 1;
+ } else if (getenv("LIBCLANG_RESOURCE_USAGE"))
+ PrintLibclangResourceUsage(TU);
+
+ return RTUI.result;
+}
+
+
+CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
+ if (!CTUnit)
+ return createCXString("");
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit->TUData);
+ return createCXString(CXXUnit->getOriginalSourceFileName(), true);
+}
+
+CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
+ ASTUnit *CXXUnit = static_cast<ASTUnit*>(TU->TUData);
+ return MakeCXCursor(CXXUnit->getASTContext().getTranslationUnitDecl(), TU);
+}
+
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// CXFile Operations.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+CXString clang_getFileName(CXFile SFile) {
+ if (!SFile)
+ return createCXString((const char*)NULL);
+
+ FileEntry *FEnt = static_cast<FileEntry *>(SFile);
+ return createCXString(FEnt->getName());
+}
+
+time_t clang_getFileTime(CXFile SFile) {
+ if (!SFile)
+ return 0;
+
+ FileEntry *FEnt = static_cast<FileEntry *>(SFile);
+ return FEnt->getModificationTime();
+}
+
+CXFile clang_getFile(CXTranslationUnit tu, const char *file_name) {
+ if (!tu)
+ return 0;
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
+
+ FileManager &FMgr = CXXUnit->getFileManager();
+ return const_cast<FileEntry *>(FMgr.getFile(file_name));
+}
+
+unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file) {
+ if (!tu || !file)
+ return 0;
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
+ FileEntry *FEnt = static_cast<FileEntry *>(file);
+ return CXXUnit->getPreprocessor().getHeaderSearchInfo()
+ .isFileMultipleIncludeGuarded(FEnt);
+}
+
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// CXCursor Operations.
+//===----------------------------------------------------------------------===//
+
+static Decl *getDeclFromExpr(Stmt *E) {
+ if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))
+ return getDeclFromExpr(CE->getSubExpr());
+
+ if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
+ return RefExpr->getDecl();
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
+ return ME->getMemberDecl();
+ if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))
+ return RE->getDecl();
+ if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(E)) {
+ if (PRE->isExplicitProperty())
+ return PRE->getExplicitProperty();
+ // It could be messaging both getter and setter as in:
+ // ++myobj.myprop;
+ // in which case prefer to associate the setter since it is less obvious
+ // from inspecting the source that the setter is going to get called.
+ if (PRE->isMessagingSetter())
+ return PRE->getImplicitPropertySetter();
+ return PRE->getImplicitPropertyGetter();
+ }
+ if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
+ return getDeclFromExpr(POE->getSyntacticForm());
+ if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
+ if (Expr *Src = OVE->getSourceExpr())
+ return getDeclFromExpr(Src);
+
+ if (CallExpr *CE = dyn_cast<CallExpr>(E))
+ return getDeclFromExpr(CE->getCallee());
+ if (CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E))
+ if (!CE->isElidable())
+ return CE->getConstructor();
+ if (ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(E))
+ return OME->getMethodDecl();
+
+ if (ObjCProtocolExpr *PE = dyn_cast<ObjCProtocolExpr>(E))
+ return PE->getProtocol();
+ if (SubstNonTypeTemplateParmPackExpr *NTTP
+ = dyn_cast<SubstNonTypeTemplateParmPackExpr>(E))
+ return NTTP->getParameterPack();
+ if (SizeOfPackExpr *SizeOfPack = dyn_cast<SizeOfPackExpr>(E))
+ if (isa<NonTypeTemplateParmDecl>(SizeOfPack->getPack()) ||
+ isa<ParmVarDecl>(SizeOfPack->getPack()))
+ return SizeOfPack->getPack();
+
+ return 0;
+}
+
+static SourceLocation getLocationFromExpr(Expr *E) {
+ if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))
+ return getLocationFromExpr(CE->getSubExpr());
+
+ if (ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E))
+ return /*FIXME:*/Msg->getLeftLoc();
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ return DRE->getLocation();
+ if (MemberExpr *Member = dyn_cast<MemberExpr>(E))
+ return Member->getMemberLoc();
+ if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E))
+ return Ivar->getLocation();
+ if (SizeOfPackExpr *SizeOfPack = dyn_cast<SizeOfPackExpr>(E))
+ return SizeOfPack->getPackLoc();
+ if (ObjCPropertyRefExpr *PropRef = dyn_cast<ObjCPropertyRefExpr>(E))
+ return PropRef->getLocation();
+
+ return E->getLocStart();
+}
+
+extern "C" {
+
+unsigned clang_visitChildren(CXCursor parent,
+ CXCursorVisitor visitor,
+ CXClientData client_data) {
+ CursorVisitor CursorVis(getCursorTU(parent), visitor, client_data,
+ /*VisitPreprocessorLast=*/false);
+ return CursorVis.VisitChildren(parent);
+}
+
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+#if __has_feature(blocks)
+typedef enum CXChildVisitResult
+ (^CXCursorVisitorBlock)(CXCursor cursor, CXCursor parent);
+
+static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,
+ CXClientData client_data) {
+ CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data;
+ return block(cursor, parent);
+}
+#else
+// If we are compiled with a compiler that doesn't have native blocks support,
+// define and call the block manually, so the
+typedef struct _CXChildVisitResult
+{
+ void *isa;
+ int flags;
+ int reserved;
+ enum CXChildVisitResult(*invoke)(struct _CXChildVisitResult*, CXCursor,
+ CXCursor);
+} *CXCursorVisitorBlock;
+
+static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,
+ CXClientData client_data) {
+ CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data;
+ return block->invoke(block, cursor, parent);
+}
+#endif
+
+
+unsigned clang_visitChildrenWithBlock(CXCursor parent,
+ CXCursorVisitorBlock block) {
+ return clang_visitChildren(parent, visitWithBlock, block);
+}
+
+static CXString getDeclSpelling(Decl *D) {
+ if (!D)
+ return createCXString("");
+
+ NamedDecl *ND = dyn_cast<NamedDecl>(D);
+ if (!ND) {
+ if (ObjCPropertyImplDecl *PropImpl =dyn_cast<ObjCPropertyImplDecl>(D))
+ if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())
+ return createCXString(Property->getIdentifier()->getName());
+
+ if (ImportDecl *ImportD = dyn_cast<ImportDecl>(D))
+ if (Module *Mod = ImportD->getImportedModule())
+ return createCXString(Mod->getFullModuleName());
+
+ return createCXString("");
+ }
+
+ if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
+ return createCXString(OMD->getSelector().getAsString());
+
+ if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
+ // No, this isn't the same as the code below. getIdentifier() is non-virtual
+ // and returns different names. NamedDecl returns the class name and
+ // ObjCCategoryImplDecl returns the category name.
+ return createCXString(CIMP->getIdentifier()->getNameStart());
+
+ if (isa<UsingDirectiveDecl>(D))
+ return createCXString("");
+
+ SmallString<1024> S;
+ llvm::raw_svector_ostream os(S);
+ ND->printName(os);
+
+ return createCXString(os.str());
+}
+
+CXString clang_getCursorSpelling(CXCursor C) {
+ if (clang_isTranslationUnit(C.kind))
+ return clang_getTranslationUnitSpelling(
+ static_cast<CXTranslationUnit>(C.data[2]));
+
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef: {
+ ObjCInterfaceDecl *Super = getCursorObjCSuperClassRef(C).first;
+ return createCXString(Super->getIdentifier()->getNameStart());
+ }
+ case CXCursor_ObjCClassRef: {
+ ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
+ return createCXString(Class->getIdentifier()->getNameStart());
+ }
+ case CXCursor_ObjCProtocolRef: {
+ ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first;
+ assert(OID && "getCursorSpelling(): Missing protocol decl");
+ return createCXString(OID->getIdentifier()->getNameStart());
+ }
+ case CXCursor_CXXBaseSpecifier: {
+ CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
+ return createCXString(B->getType().getAsString());
+ }
+ case CXCursor_TypeRef: {
+ TypeDecl *Type = getCursorTypeRef(C).first;
+ assert(Type && "Missing type decl");
+
+ return createCXString(getCursorContext(C).getTypeDeclType(Type).
+ getAsString());
+ }
+ case CXCursor_TemplateRef: {
+ TemplateDecl *Template = getCursorTemplateRef(C).first;
+ assert(Template && "Missing template decl");
+
+ return createCXString(Template->getNameAsString());
+ }
+
+ case CXCursor_NamespaceRef: {
+ NamedDecl *NS = getCursorNamespaceRef(C).first;
+ assert(NS && "Missing namespace decl");
+
+ return createCXString(NS->getNameAsString());
+ }
+
+ case CXCursor_MemberRef: {
+ FieldDecl *Field = getCursorMemberRef(C).first;
+ assert(Field && "Missing member decl");
+
+ return createCXString(Field->getNameAsString());
+ }
+
+ case CXCursor_LabelRef: {
+ LabelStmt *Label = getCursorLabelRef(C).first;
+ assert(Label && "Missing label");
+
+ return createCXString(Label->getName());
+ }
+
+ case CXCursor_OverloadedDeclRef: {
+ OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;
+ if (Decl *D = Storage.dyn_cast<Decl *>()) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ return createCXString(ND->getNameAsString());
+ return createCXString("");
+ }
+ if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>())
+ return createCXString(E->getName().getAsString());
+ OverloadedTemplateStorage *Ovl
+ = Storage.get<OverloadedTemplateStorage*>();
+ if (Ovl->size() == 0)
+ return createCXString("");
+ return createCXString((*Ovl->begin())->getNameAsString());
+ }
+
+ case CXCursor_VariableRef: {
+ VarDecl *Var = getCursorVariableRef(C).first;
+ assert(Var && "Missing variable decl");
+
+ return createCXString(Var->getNameAsString());
+ }
+
+ default:
+ return createCXString("<not implemented>");
+ }
+ }
+
+ if (clang_isExpression(C.kind)) {
+ Decl *D = getDeclFromExpr(getCursorExpr(C));
+ if (D)
+ return getDeclSpelling(D);
+ return createCXString("");
+ }
+
+ if (clang_isStatement(C.kind)) {
+ Stmt *S = getCursorStmt(C);
+ if (LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))
+ return createCXString(Label->getName());
+
+ return createCXString("");
+ }
+
+ if (C.kind == CXCursor_MacroExpansion)
+ return createCXString(getCursorMacroExpansion(C)->getName()
+ ->getNameStart());
+
+ if (C.kind == CXCursor_MacroDefinition)
+ return createCXString(getCursorMacroDefinition(C)->getName()
+ ->getNameStart());
+
+ if (C.kind == CXCursor_InclusionDirective)
+ return createCXString(getCursorInclusionDirective(C)->getFileName());
+
+ if (clang_isDeclaration(C.kind))
+ return getDeclSpelling(getCursorDecl(C));
+
+ if (C.kind == CXCursor_AnnotateAttr) {
+ AnnotateAttr *AA = cast<AnnotateAttr>(cxcursor::getCursorAttr(C));
+ return createCXString(AA->getAnnotation());
+ }
+
+ if (C.kind == CXCursor_AsmLabelAttr) {
+ AsmLabelAttr *AA = cast<AsmLabelAttr>(cxcursor::getCursorAttr(C));
+ return createCXString(AA->getLabel());
+ }
+
+ return createCXString("");
+}
+
+CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor C,
+ unsigned pieceIndex,
+ unsigned options) {
+ if (clang_Cursor_isNull(C))
+ return clang_getNullRange();
+
+ ASTContext &Ctx = getCursorContext(C);
+
+ if (clang_isStatement(C.kind)) {
+ Stmt *S = getCursorStmt(C);
+ if (LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S)) {
+ if (pieceIndex > 0)
+ return clang_getNullRange();
+ return cxloc::translateSourceRange(Ctx, Label->getIdentLoc());
+ }
+
+ return clang_getNullRange();
+ }
+
+ if (C.kind == CXCursor_ObjCMessageExpr) {
+ if (ObjCMessageExpr *
+ ME = dyn_cast_or_null<ObjCMessageExpr>(getCursorExpr(C))) {
+ if (pieceIndex >= ME->getNumSelectorLocs())
+ return clang_getNullRange();
+ return cxloc::translateSourceRange(Ctx, ME->getSelectorLoc(pieceIndex));
+ }
+ }
+
+ if (C.kind == CXCursor_ObjCInstanceMethodDecl ||
+ C.kind == CXCursor_ObjCClassMethodDecl) {
+ if (ObjCMethodDecl *
+ MD = dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(C))) {
+ if (pieceIndex >= MD->getNumSelectorLocs())
+ return clang_getNullRange();
+ return cxloc::translateSourceRange(Ctx, MD->getSelectorLoc(pieceIndex));
+ }
+ }
+
+ if (C.kind == CXCursor_ObjCCategoryDecl ||
+ C.kind == CXCursor_ObjCCategoryImplDecl) {
+ if (pieceIndex > 0)
+ return clang_getNullRange();
+ if (ObjCCategoryDecl *
+ CD = dyn_cast_or_null<ObjCCategoryDecl>(getCursorDecl(C)))
+ return cxloc::translateSourceRange(Ctx, CD->getCategoryNameLoc());
+ if (ObjCCategoryImplDecl *
+ CID = dyn_cast_or_null<ObjCCategoryImplDecl>(getCursorDecl(C)))
+ return cxloc::translateSourceRange(Ctx, CID->getCategoryNameLoc());
+ }
+
+ if (C.kind == CXCursor_ModuleImportDecl) {
+ if (pieceIndex > 0)
+ return clang_getNullRange();
+ if (ImportDecl *ImportD = dyn_cast_or_null<ImportDecl>(getCursorDecl(C))) {
+ ArrayRef<SourceLocation> Locs = ImportD->getIdentifierLocs();
+ if (!Locs.empty())
+ return cxloc::translateSourceRange(Ctx,
+ SourceRange(Locs.front(), Locs.back()));
+ }
+ return clang_getNullRange();
+ }
+
+ // FIXME: A CXCursor_InclusionDirective should give the location of the
+ // filename, but we don't keep track of this.
+
+ // FIXME: A CXCursor_AnnotateAttr should give the location of the annotation
+ // but we don't keep track of this.
+
+ // FIXME: A CXCursor_AsmLabelAttr should give the location of the label
+ // but we don't keep track of this.
+
+ // Default handling, give the location of the cursor.
+
+ if (pieceIndex > 0)
+ return clang_getNullRange();
+
+ CXSourceLocation CXLoc = clang_getCursorLocation(C);
+ SourceLocation Loc = cxloc::translateSourceLocation(CXLoc);
+ return cxloc::translateSourceRange(Ctx, Loc);
+}
+
+CXString clang_getCursorDisplayName(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return clang_getCursorSpelling(C);
+
+ Decl *D = getCursorDecl(C);
+ if (!D)
+ return createCXString("");
+
+ PrintingPolicy Policy = getCursorContext(C).getPrintingPolicy();
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
+ D = FunTmpl->getTemplatedDecl();
+
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ SmallString<64> Str;
+ llvm::raw_svector_ostream OS(Str);
+ OS << *Function;
+ if (Function->getPrimaryTemplate())
+ OS << "<>";
+ OS << "(";
+ for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) {
+ if (I)
+ OS << ", ";
+ OS << Function->getParamDecl(I)->getType().getAsString(Policy);
+ }
+
+ if (Function->isVariadic()) {
+ if (Function->getNumParams())
+ OS << ", ";
+ OS << "...";
+ }
+ OS << ")";
+ return createCXString(OS.str());
+ }
+
+ if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) {
+ SmallString<64> Str;
+ llvm::raw_svector_ostream OS(Str);
+ OS << *ClassTemplate;
+ OS << "<";
+ TemplateParameterList *Params = ClassTemplate->getTemplateParameters();
+ for (unsigned I = 0, N = Params->size(); I != N; ++I) {
+ if (I)
+ OS << ", ";
+
+ NamedDecl *Param = Params->getParam(I);
+ if (Param->getIdentifier()) {
+ OS << Param->getIdentifier()->getName();
+ continue;
+ }
+
+ // There is no parameter name, which makes this tricky. Try to come up
+ // with something useful that isn't too long.
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+ OS << (TTP->wasDeclaredWithTypename()? "typename" : "class");
+ else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Param))
+ OS << NTTP->getType().getAsString(Policy);
+ else
+ OS << "template<...> class";
+ }
+
+ OS << ">";
+ return createCXString(OS.str());
+ }
+
+ if (ClassTemplateSpecializationDecl *ClassSpec
+ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ // If the type was explicitly written, use that.
+ if (TypeSourceInfo *TSInfo = ClassSpec->getTypeAsWritten())
+ return createCXString(TSInfo->getType().getAsString(Policy));
+
+ SmallString<64> Str;
+ llvm::raw_svector_ostream OS(Str);
+ OS << *ClassSpec;
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ ClassSpec->getTemplateArgs().data(),
+ ClassSpec->getTemplateArgs().size(),
+ Policy);
+ return createCXString(OS.str());
+ }
+
+ return clang_getCursorSpelling(C);
+}
+
+CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
+ switch (Kind) {
+ case CXCursor_FunctionDecl:
+ return createCXString("FunctionDecl");
+ case CXCursor_TypedefDecl:
+ return createCXString("TypedefDecl");
+ case CXCursor_EnumDecl:
+ return createCXString("EnumDecl");
+ case CXCursor_EnumConstantDecl:
+ return createCXString("EnumConstantDecl");
+ case CXCursor_StructDecl:
+ return createCXString("StructDecl");
+ case CXCursor_UnionDecl:
+ return createCXString("UnionDecl");
+ case CXCursor_ClassDecl:
+ return createCXString("ClassDecl");
+ case CXCursor_FieldDecl:
+ return createCXString("FieldDecl");
+ case CXCursor_VarDecl:
+ return createCXString("VarDecl");
+ case CXCursor_ParmDecl:
+ return createCXString("ParmDecl");
+ case CXCursor_ObjCInterfaceDecl:
+ return createCXString("ObjCInterfaceDecl");
+ case CXCursor_ObjCCategoryDecl:
+ return createCXString("ObjCCategoryDecl");
+ case CXCursor_ObjCProtocolDecl:
+ return createCXString("ObjCProtocolDecl");
+ case CXCursor_ObjCPropertyDecl:
+ return createCXString("ObjCPropertyDecl");
+ case CXCursor_ObjCIvarDecl:
+ return createCXString("ObjCIvarDecl");
+ case CXCursor_ObjCInstanceMethodDecl:
+ return createCXString("ObjCInstanceMethodDecl");
+ case CXCursor_ObjCClassMethodDecl:
+ return createCXString("ObjCClassMethodDecl");
+ case CXCursor_ObjCImplementationDecl:
+ return createCXString("ObjCImplementationDecl");
+ case CXCursor_ObjCCategoryImplDecl:
+ return createCXString("ObjCCategoryImplDecl");
+ case CXCursor_CXXMethod:
+ return createCXString("CXXMethod");
+ case CXCursor_UnexposedDecl:
+ return createCXString("UnexposedDecl");
+ case CXCursor_ObjCSuperClassRef:
+ return createCXString("ObjCSuperClassRef");
+ case CXCursor_ObjCProtocolRef:
+ return createCXString("ObjCProtocolRef");
+ case CXCursor_ObjCClassRef:
+ return createCXString("ObjCClassRef");
+ case CXCursor_TypeRef:
+ return createCXString("TypeRef");
+ case CXCursor_TemplateRef:
+ return createCXString("TemplateRef");
+ case CXCursor_NamespaceRef:
+ return createCXString("NamespaceRef");
+ case CXCursor_MemberRef:
+ return createCXString("MemberRef");
+ case CXCursor_LabelRef:
+ return createCXString("LabelRef");
+ case CXCursor_OverloadedDeclRef:
+ return createCXString("OverloadedDeclRef");
+ case CXCursor_VariableRef:
+ return createCXString("VariableRef");
+ case CXCursor_IntegerLiteral:
+ return createCXString("IntegerLiteral");
+ case CXCursor_FloatingLiteral:
+ return createCXString("FloatingLiteral");
+ case CXCursor_ImaginaryLiteral:
+ return createCXString("ImaginaryLiteral");
+ case CXCursor_StringLiteral:
+ return createCXString("StringLiteral");
+ case CXCursor_CharacterLiteral:
+ return createCXString("CharacterLiteral");
+ case CXCursor_ParenExpr:
+ return createCXString("ParenExpr");
+ case CXCursor_UnaryOperator:
+ return createCXString("UnaryOperator");
+ case CXCursor_ArraySubscriptExpr:
+ return createCXString("ArraySubscriptExpr");
+ case CXCursor_BinaryOperator:
+ return createCXString("BinaryOperator");
+ case CXCursor_CompoundAssignOperator:
+ return createCXString("CompoundAssignOperator");
+ case CXCursor_ConditionalOperator:
+ return createCXString("ConditionalOperator");
+ case CXCursor_CStyleCastExpr:
+ return createCXString("CStyleCastExpr");
+ case CXCursor_CompoundLiteralExpr:
+ return createCXString("CompoundLiteralExpr");
+ case CXCursor_InitListExpr:
+ return createCXString("InitListExpr");
+ case CXCursor_AddrLabelExpr:
+ return createCXString("AddrLabelExpr");
+ case CXCursor_StmtExpr:
+ return createCXString("StmtExpr");
+ case CXCursor_GenericSelectionExpr:
+ return createCXString("GenericSelectionExpr");
+ case CXCursor_GNUNullExpr:
+ return createCXString("GNUNullExpr");
+ case CXCursor_CXXStaticCastExpr:
+ return createCXString("CXXStaticCastExpr");
+ case CXCursor_CXXDynamicCastExpr:
+ return createCXString("CXXDynamicCastExpr");
+ case CXCursor_CXXReinterpretCastExpr:
+ return createCXString("CXXReinterpretCastExpr");
+ case CXCursor_CXXConstCastExpr:
+ return createCXString("CXXConstCastExpr");
+ case CXCursor_CXXFunctionalCastExpr:
+ return createCXString("CXXFunctionalCastExpr");
+ case CXCursor_CXXTypeidExpr:
+ return createCXString("CXXTypeidExpr");
+ case CXCursor_CXXBoolLiteralExpr:
+ return createCXString("CXXBoolLiteralExpr");
+ case CXCursor_CXXNullPtrLiteralExpr:
+ return createCXString("CXXNullPtrLiteralExpr");
+ case CXCursor_CXXThisExpr:
+ return createCXString("CXXThisExpr");
+ case CXCursor_CXXThrowExpr:
+ return createCXString("CXXThrowExpr");
+ case CXCursor_CXXNewExpr:
+ return createCXString("CXXNewExpr");
+ case CXCursor_CXXDeleteExpr:
+ return createCXString("CXXDeleteExpr");
+ case CXCursor_UnaryExpr:
+ return createCXString("UnaryExpr");
+ case CXCursor_ObjCStringLiteral:
+ return createCXString("ObjCStringLiteral");
+ case CXCursor_ObjCBoolLiteralExpr:
+ return createCXString("ObjCBoolLiteralExpr");
+ case CXCursor_ObjCEncodeExpr:
+ return createCXString("ObjCEncodeExpr");
+ case CXCursor_ObjCSelectorExpr:
+ return createCXString("ObjCSelectorExpr");
+ case CXCursor_ObjCProtocolExpr:
+ return createCXString("ObjCProtocolExpr");
+ case CXCursor_ObjCBridgedCastExpr:
+ return createCXString("ObjCBridgedCastExpr");
+ case CXCursor_BlockExpr:
+ return createCXString("BlockExpr");
+ case CXCursor_PackExpansionExpr:
+ return createCXString("PackExpansionExpr");
+ case CXCursor_SizeOfPackExpr:
+ return createCXString("SizeOfPackExpr");
+ case CXCursor_LambdaExpr:
+ return createCXString("LambdaExpr");
+ case CXCursor_UnexposedExpr:
+ return createCXString("UnexposedExpr");
+ case CXCursor_DeclRefExpr:
+ return createCXString("DeclRefExpr");
+ case CXCursor_MemberRefExpr:
+ return createCXString("MemberRefExpr");
+ case CXCursor_CallExpr:
+ return createCXString("CallExpr");
+ case CXCursor_ObjCMessageExpr:
+ return createCXString("ObjCMessageExpr");
+ case CXCursor_UnexposedStmt:
+ return createCXString("UnexposedStmt");
+ case CXCursor_DeclStmt:
+ return createCXString("DeclStmt");
+ case CXCursor_LabelStmt:
+ return createCXString("LabelStmt");
+ case CXCursor_CompoundStmt:
+ return createCXString("CompoundStmt");
+ case CXCursor_CaseStmt:
+ return createCXString("CaseStmt");
+ case CXCursor_DefaultStmt:
+ return createCXString("DefaultStmt");
+ case CXCursor_IfStmt:
+ return createCXString("IfStmt");
+ case CXCursor_SwitchStmt:
+ return createCXString("SwitchStmt");
+ case CXCursor_WhileStmt:
+ return createCXString("WhileStmt");
+ case CXCursor_DoStmt:
+ return createCXString("DoStmt");
+ case CXCursor_ForStmt:
+ return createCXString("ForStmt");
+ case CXCursor_GotoStmt:
+ return createCXString("GotoStmt");
+ case CXCursor_IndirectGotoStmt:
+ return createCXString("IndirectGotoStmt");
+ case CXCursor_ContinueStmt:
+ return createCXString("ContinueStmt");
+ case CXCursor_BreakStmt:
+ return createCXString("BreakStmt");
+ case CXCursor_ReturnStmt:
+ return createCXString("ReturnStmt");
+ case CXCursor_GCCAsmStmt:
+ return createCXString("GCCAsmStmt");
+ case CXCursor_MSAsmStmt:
+ return createCXString("MSAsmStmt");
+ case CXCursor_ObjCAtTryStmt:
+ return createCXString("ObjCAtTryStmt");
+ case CXCursor_ObjCAtCatchStmt:
+ return createCXString("ObjCAtCatchStmt");
+ case CXCursor_ObjCAtFinallyStmt:
+ return createCXString("ObjCAtFinallyStmt");
+ case CXCursor_ObjCAtThrowStmt:
+ return createCXString("ObjCAtThrowStmt");
+ case CXCursor_ObjCAtSynchronizedStmt:
+ return createCXString("ObjCAtSynchronizedStmt");
+ case CXCursor_ObjCAutoreleasePoolStmt:
+ return createCXString("ObjCAutoreleasePoolStmt");
+ case CXCursor_ObjCForCollectionStmt:
+ return createCXString("ObjCForCollectionStmt");
+ case CXCursor_CXXCatchStmt:
+ return createCXString("CXXCatchStmt");
+ case CXCursor_CXXTryStmt:
+ return createCXString("CXXTryStmt");
+ case CXCursor_CXXForRangeStmt:
+ return createCXString("CXXForRangeStmt");
+ case CXCursor_SEHTryStmt:
+ return createCXString("SEHTryStmt");
+ case CXCursor_SEHExceptStmt:
+ return createCXString("SEHExceptStmt");
+ case CXCursor_SEHFinallyStmt:
+ return createCXString("SEHFinallyStmt");
+ case CXCursor_NullStmt:
+ return createCXString("NullStmt");
+ case CXCursor_InvalidFile:
+ return createCXString("InvalidFile");
+ case CXCursor_InvalidCode:
+ return createCXString("InvalidCode");
+ case CXCursor_NoDeclFound:
+ return createCXString("NoDeclFound");
+ case CXCursor_NotImplemented:
+ return createCXString("NotImplemented");
+ case CXCursor_TranslationUnit:
+ return createCXString("TranslationUnit");
+ case CXCursor_UnexposedAttr:
+ return createCXString("UnexposedAttr");
+ case CXCursor_IBActionAttr:
+ return createCXString("attribute(ibaction)");
+ case CXCursor_IBOutletAttr:
+ return createCXString("attribute(iboutlet)");
+ case CXCursor_IBOutletCollectionAttr:
+ return createCXString("attribute(iboutletcollection)");
+ case CXCursor_CXXFinalAttr:
+ return createCXString("attribute(final)");
+ case CXCursor_CXXOverrideAttr:
+ return createCXString("attribute(override)");
+ case CXCursor_AnnotateAttr:
+ return createCXString("attribute(annotate)");
+ case CXCursor_AsmLabelAttr:
+ return createCXString("asm label");
+ case CXCursor_PreprocessingDirective:
+ return createCXString("preprocessing directive");
+ case CXCursor_MacroDefinition:
+ return createCXString("macro definition");
+ case CXCursor_MacroExpansion:
+ return createCXString("macro expansion");
+ case CXCursor_InclusionDirective:
+ return createCXString("inclusion directive");
+ case CXCursor_Namespace:
+ return createCXString("Namespace");
+ case CXCursor_LinkageSpec:
+ return createCXString("LinkageSpec");
+ case CXCursor_CXXBaseSpecifier:
+ return createCXString("C++ base class specifier");
+ case CXCursor_Constructor:
+ return createCXString("CXXConstructor");
+ case CXCursor_Destructor:
+ return createCXString("CXXDestructor");
+ case CXCursor_ConversionFunction:
+ return createCXString("CXXConversion");
+ case CXCursor_TemplateTypeParameter:
+ return createCXString("TemplateTypeParameter");
+ case CXCursor_NonTypeTemplateParameter:
+ return createCXString("NonTypeTemplateParameter");
+ case CXCursor_TemplateTemplateParameter:
+ return createCXString("TemplateTemplateParameter");
+ case CXCursor_FunctionTemplate:
+ return createCXString("FunctionTemplate");
+ case CXCursor_ClassTemplate:
+ return createCXString("ClassTemplate");
+ case CXCursor_ClassTemplatePartialSpecialization:
+ return createCXString("ClassTemplatePartialSpecialization");
+ case CXCursor_NamespaceAlias:
+ return createCXString("NamespaceAlias");
+ case CXCursor_UsingDirective:
+ return createCXString("UsingDirective");
+ case CXCursor_UsingDeclaration:
+ return createCXString("UsingDeclaration");
+ case CXCursor_TypeAliasDecl:
+ return createCXString("TypeAliasDecl");
+ case CXCursor_ObjCSynthesizeDecl:
+ return createCXString("ObjCSynthesizeDecl");
+ case CXCursor_ObjCDynamicDecl:
+ return createCXString("ObjCDynamicDecl");
+ case CXCursor_CXXAccessSpecifier:
+ return createCXString("CXXAccessSpecifier");
+ case CXCursor_ModuleImportDecl:
+ return createCXString("ModuleImport");
+ }
+
+ llvm_unreachable("Unhandled CXCursorKind");
+}
+
+struct GetCursorData {
+ SourceLocation TokenBeginLoc;
+ bool PointsAtMacroArgExpansion;
+ bool VisitedObjCPropertyImplDecl;
+ SourceLocation VisitedDeclaratorDeclStartLoc;
+ CXCursor &BestCursor;
+
+ GetCursorData(SourceManager &SM,
+ SourceLocation tokenBegin, CXCursor &outputCursor)
+ : TokenBeginLoc(tokenBegin), BestCursor(outputCursor) {
+ PointsAtMacroArgExpansion = SM.isMacroArgExpansion(tokenBegin);
+ VisitedObjCPropertyImplDecl = false;
+ }
+};
+
+static enum CXChildVisitResult GetCursorVisitor(CXCursor cursor,
+ CXCursor parent,
+ CXClientData client_data) {
+ GetCursorData *Data = static_cast<GetCursorData *>(client_data);
+ CXCursor *BestCursor = &Data->BestCursor;
+
+ // If we point inside a macro argument we should provide info of what the
+ // token is so use the actual cursor, don't replace it with a macro expansion
+ // cursor.
+ if (cursor.kind == CXCursor_MacroExpansion && Data->PointsAtMacroArgExpansion)
+ return CXChildVisit_Recurse;
+
+ if (clang_isDeclaration(cursor.kind)) {
+ // Avoid having the implicit methods override the property decls.
+ if (ObjCMethodDecl *MD
+ = dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {
+ if (MD->isImplicit())
+ return CXChildVisit_Break;
+
+ } else if (ObjCInterfaceDecl *ID
+ = dyn_cast_or_null<ObjCInterfaceDecl>(getCursorDecl(cursor))) {
+ // Check that when we have multiple @class references in the same line,
+ // that later ones do not override the previous ones.
+ // If we have:
+ // @class Foo, Bar;
+ // source ranges for both start at '@', so 'Bar' will end up overriding
+ // 'Foo' even though the cursor location was at 'Foo'.
+ if (BestCursor->kind == CXCursor_ObjCInterfaceDecl ||
+ BestCursor->kind == CXCursor_ObjCClassRef)
+ if (ObjCInterfaceDecl *PrevID
+ = dyn_cast_or_null<ObjCInterfaceDecl>(getCursorDecl(*BestCursor))){
+ if (PrevID != ID &&
+ !PrevID->isThisDeclarationADefinition() &&
+ !ID->isThisDeclarationADefinition())
+ return CXChildVisit_Break;
+ }
+
+ } else if (DeclaratorDecl *DD
+ = dyn_cast_or_null<DeclaratorDecl>(getCursorDecl(cursor))) {
+ SourceLocation StartLoc = DD->getSourceRange().getBegin();
+ // Check that when we have multiple declarators in the same line,
+ // that later ones do not override the previous ones.
+ // If we have:
+ // int Foo, Bar;
+ // source ranges for both start at 'int', so 'Bar' will end up overriding
+ // 'Foo' even though the cursor location was at 'Foo'.
+ if (Data->VisitedDeclaratorDeclStartLoc == StartLoc)
+ return CXChildVisit_Break;
+ Data->VisitedDeclaratorDeclStartLoc = StartLoc;
+
+ } else if (ObjCPropertyImplDecl *PropImp
+ = dyn_cast_or_null<ObjCPropertyImplDecl>(getCursorDecl(cursor))) {
+ (void)PropImp;
+ // Check that when we have multiple @synthesize in the same line,
+ // that later ones do not override the previous ones.
+ // If we have:
+ // @synthesize Foo, Bar;
+ // source ranges for both start at '@', so 'Bar' will end up overriding
+ // 'Foo' even though the cursor location was at 'Foo'.
+ if (Data->VisitedObjCPropertyImplDecl)
+ return CXChildVisit_Break;
+ Data->VisitedObjCPropertyImplDecl = true;
+ }
+ }
+
+ if (clang_isExpression(cursor.kind) &&
+ clang_isDeclaration(BestCursor->kind)) {
+ if (Decl *D = getCursorDecl(*BestCursor)) {
+ // Avoid having the cursor of an expression replace the declaration cursor
+ // when the expression source range overlaps the declaration range.
+ // This can happen for C++ constructor expressions whose range generally
+ // include the variable declaration, e.g.:
+ // MyCXXClass foo; // Make sure pointing at 'foo' returns a VarDecl cursor.
+ if (D->getLocation().isValid() && Data->TokenBeginLoc.isValid() &&
+ D->getLocation() == Data->TokenBeginLoc)
+ return CXChildVisit_Break;
+ }
+ }
+
+ // If our current best cursor is the construction of a temporary object,
+ // don't replace that cursor with a type reference, because we want
+ // clang_getCursor() to point at the constructor.
+ if (clang_isExpression(BestCursor->kind) &&
+ isa<CXXTemporaryObjectExpr>(getCursorExpr(*BestCursor)) &&
+ cursor.kind == CXCursor_TypeRef) {
+ // Keep the cursor pointing at CXXTemporaryObjectExpr but also mark it
+ // as having the actual point on the type reference.
+ *BestCursor = getTypeRefedCallExprCursor(*BestCursor);
+ return CXChildVisit_Recurse;
+ }
+
+ *BestCursor = cursor;
+ return CXChildVisit_Recurse;
+}
+
+CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
+ if (!TU)
+ return clang_getNullCursor();
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ SourceLocation SLoc = cxloc::translateSourceLocation(Loc);
+ CXCursor Result = cxcursor::getCursor(TU, SLoc);
+
+ bool Logging = getenv("LIBCLANG_LOGGING");
+ if (Logging) {
+ CXFile SearchFile;
+ unsigned SearchLine, SearchColumn;
+ CXFile ResultFile;
+ unsigned ResultLine, ResultColumn;
+ CXString SearchFileName, ResultFileName, KindSpelling, USR;
+ const char *IsDef = clang_isCursorDefinition(Result)? " (Definition)" : "";
+ CXSourceLocation ResultLoc = clang_getCursorLocation(Result);
+
+ clang_getExpansionLocation(Loc, &SearchFile, &SearchLine, &SearchColumn, 0);
+ clang_getExpansionLocation(ResultLoc, &ResultFile, &ResultLine,
+ &ResultColumn, 0);
+ SearchFileName = clang_getFileName(SearchFile);
+ ResultFileName = clang_getFileName(ResultFile);
+ KindSpelling = clang_getCursorKindSpelling(Result.kind);
+ USR = clang_getCursorUSR(Result);
+ fprintf(stderr, "clang_getCursor(%s:%d:%d) = %s(%s:%d:%d):%s%s\n",
+ clang_getCString(SearchFileName), SearchLine, SearchColumn,
+ clang_getCString(KindSpelling),
+ clang_getCString(ResultFileName), ResultLine, ResultColumn,
+ clang_getCString(USR), IsDef);
+ clang_disposeString(SearchFileName);
+ clang_disposeString(ResultFileName);
+ clang_disposeString(KindSpelling);
+ clang_disposeString(USR);
+
+ CXCursor Definition = clang_getCursorDefinition(Result);
+ if (!clang_equalCursors(Definition, clang_getNullCursor())) {
+ CXSourceLocation DefinitionLoc = clang_getCursorLocation(Definition);
+ CXString DefinitionKindSpelling
+ = clang_getCursorKindSpelling(Definition.kind);
+ CXFile DefinitionFile;
+ unsigned DefinitionLine, DefinitionColumn;
+ clang_getExpansionLocation(DefinitionLoc, &DefinitionFile,
+ &DefinitionLine, &DefinitionColumn, 0);
+ CXString DefinitionFileName = clang_getFileName(DefinitionFile);
+ fprintf(stderr, " -> %s(%s:%d:%d)\n",
+ clang_getCString(DefinitionKindSpelling),
+ clang_getCString(DefinitionFileName),
+ DefinitionLine, DefinitionColumn);
+ clang_disposeString(DefinitionFileName);
+ clang_disposeString(DefinitionKindSpelling);
+ }
+ }
+
+ return Result;
+}
+
+CXCursor clang_getNullCursor(void) {
+ return MakeCXCursorInvalid(CXCursor_InvalidFile);
+}
+
+unsigned clang_equalCursors(CXCursor X, CXCursor Y) {
+ return X == Y;
+}
+
+unsigned clang_hashCursor(CXCursor C) {
+ unsigned Index = 0;
+ if (clang_isExpression(C.kind) || clang_isStatement(C.kind))
+ Index = 1;
+
+ return llvm::DenseMapInfo<std::pair<unsigned, void*> >::getHashValue(
+ std::make_pair(C.kind, C.data[Index]));
+}
+
+unsigned clang_isInvalid(enum CXCursorKind K) {
+ return K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid;
+}
+
+unsigned clang_isDeclaration(enum CXCursorKind K) {
+ return (K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl) ||
+ (K >= CXCursor_FirstExtraDecl && K <= CXCursor_LastExtraDecl);
+}
+
+unsigned clang_isReference(enum CXCursorKind K) {
+ return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
+}
+
+unsigned clang_isExpression(enum CXCursorKind K) {
+ return K >= CXCursor_FirstExpr && K <= CXCursor_LastExpr;
+}
+
+unsigned clang_isStatement(enum CXCursorKind K) {
+ return K >= CXCursor_FirstStmt && K <= CXCursor_LastStmt;
+}
+
+unsigned clang_isAttribute(enum CXCursorKind K) {
+ return K >= CXCursor_FirstAttr && K <= CXCursor_LastAttr;
+}
+
+unsigned clang_isTranslationUnit(enum CXCursorKind K) {
+ return K == CXCursor_TranslationUnit;
+}
+
+unsigned clang_isPreprocessing(enum CXCursorKind K) {
+ return K >= CXCursor_FirstPreprocessing && K <= CXCursor_LastPreprocessing;
+}
+
+unsigned clang_isUnexposed(enum CXCursorKind K) {
+ switch (K) {
+ case CXCursor_UnexposedDecl:
+ case CXCursor_UnexposedExpr:
+ case CXCursor_UnexposedStmt:
+ case CXCursor_UnexposedAttr:
+ return true;
+ default:
+ return false;
+ }
+}
+
+CXCursorKind clang_getCursorKind(CXCursor C) {
+ return C.kind;
+}
+
+CXSourceLocation clang_getCursorLocation(CXCursor C) {
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCSuperClassRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCProtocolRef: {
+ std::pair<ObjCProtocolDecl *, SourceLocation> P
+ = getCursorObjCProtocolRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCClassRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_TypeRef: {
+ std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_TemplateRef: {
+ std::pair<TemplateDecl *, SourceLocation> P = getCursorTemplateRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_NamespaceRef: {
+ std::pair<NamedDecl *, SourceLocation> P = getCursorNamespaceRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_MemberRef: {
+ std::pair<FieldDecl *, SourceLocation> P = getCursorMemberRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_VariableRef: {
+ std::pair<VarDecl *, SourceLocation> P = getCursorVariableRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_CXXBaseSpecifier: {
+ CXXBaseSpecifier *BaseSpec = getCursorCXXBaseSpecifier(C);
+ if (!BaseSpec)
+ return clang_getNullLocation();
+
+ if (TypeSourceInfo *TSInfo = BaseSpec->getTypeSourceInfo())
+ return cxloc::translateSourceLocation(getCursorContext(C),
+ TSInfo->getTypeLoc().getBeginLoc());
+
+ return cxloc::translateSourceLocation(getCursorContext(C),
+ BaseSpec->getLocStart());
+ }
+
+ case CXCursor_LabelRef: {
+ std::pair<LabelStmt *, SourceLocation> P = getCursorLabelRef(C);
+ return cxloc::translateSourceLocation(getCursorContext(C), P.second);
+ }
+
+ case CXCursor_OverloadedDeclRef:
+ return cxloc::translateSourceLocation(getCursorContext(C),
+ getCursorOverloadedDeclRef(C).second);
+
+ default:
+ // FIXME: Need a way to enumerate all non-reference cases.
+ llvm_unreachable("Missed a reference kind");
+ }
+ }
+
+ if (clang_isExpression(C.kind))
+ return cxloc::translateSourceLocation(getCursorContext(C),
+ getLocationFromExpr(getCursorExpr(C)));
+
+ if (clang_isStatement(C.kind))
+ return cxloc::translateSourceLocation(getCursorContext(C),
+ getCursorStmt(C)->getLocStart());
+
+ if (C.kind == CXCursor_PreprocessingDirective) {
+ SourceLocation L = cxcursor::getCursorPreprocessingDirective(C).getBegin();
+ return cxloc::translateSourceLocation(getCursorContext(C), L);
+ }
+
+ if (C.kind == CXCursor_MacroExpansion) {
+ SourceLocation L
+ = cxcursor::getCursorMacroExpansion(C)->getSourceRange().getBegin();
+ return cxloc::translateSourceLocation(getCursorContext(C), L);
+ }
+
+ if (C.kind == CXCursor_MacroDefinition) {
+ SourceLocation L = cxcursor::getCursorMacroDefinition(C)->getLocation();
+ return cxloc::translateSourceLocation(getCursorContext(C), L);
+ }
+
+ if (C.kind == CXCursor_InclusionDirective) {
+ SourceLocation L
+ = cxcursor::getCursorInclusionDirective(C)->getSourceRange().getBegin();
+ return cxloc::translateSourceLocation(getCursorContext(C), L);
+ }
+
+ if (!clang_isDeclaration(C.kind))
+ return clang_getNullLocation();
+
+ Decl *D = getCursorDecl(C);
+ if (!D)
+ return clang_getNullLocation();
+
+ SourceLocation Loc = D->getLocation();
+ // FIXME: Multiple variables declared in a single declaration
+ // currently lack the information needed to correctly determine their
+ // ranges when accounting for the type-specifier. We use context
+ // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
+ // and if so, whether it is the first decl.
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (!cxcursor::isFirstInDeclGroup(C))
+ Loc = VD->getLocation();
+ }
+
+ // For ObjC methods, give the start location of the method name.
+ if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ Loc = MD->getSelectorStartLoc();
+
+ return cxloc::translateSourceLocation(getCursorContext(C), Loc);
+}
+
+} // end extern "C"
+
+CXCursor cxcursor::getCursor(CXTranslationUnit TU, SourceLocation SLoc) {
+ assert(TU);
+
+ // Guard against an invalid SourceLocation, or we may assert in one
+ // of the following calls.
+ if (SLoc.isInvalid())
+ return clang_getNullCursor();
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
+
+ // Translate the given source location to make it point at the beginning of
+ // the token under the cursor.
+ SLoc = Lexer::GetBeginningOfToken(SLoc, CXXUnit->getSourceManager(),
+ CXXUnit->getASTContext().getLangOpts());
+
+ CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
+ if (SLoc.isValid()) {
+ GetCursorData ResultData(CXXUnit->getSourceManager(), SLoc, Result);
+ CursorVisitor CursorVis(TU, GetCursorVisitor, &ResultData,
+ /*VisitPreprocessorLast=*/true,
+ /*VisitIncludedEntities=*/false,
+ SourceLocation(SLoc));
+ CursorVis.visitFileRegion();
+ }
+
+ return Result;
+}
+
+static SourceRange getRawCursorExtent(CXCursor C) {
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef:
+ return getCursorObjCSuperClassRef(C).second;
+
+ case CXCursor_ObjCProtocolRef:
+ return getCursorObjCProtocolRef(C).second;
+
+ case CXCursor_ObjCClassRef:
+ return getCursorObjCClassRef(C).second;
+
+ case CXCursor_TypeRef:
+ return getCursorTypeRef(C).second;
+
+ case CXCursor_TemplateRef:
+ return getCursorTemplateRef(C).second;
+
+ case CXCursor_NamespaceRef:
+ return getCursorNamespaceRef(C).second;
+
+ case CXCursor_MemberRef:
+ return getCursorMemberRef(C).second;
+
+ case CXCursor_CXXBaseSpecifier:
+ return getCursorCXXBaseSpecifier(C)->getSourceRange();
+
+ case CXCursor_LabelRef:
+ return getCursorLabelRef(C).second;
+
+ case CXCursor_OverloadedDeclRef:
+ return getCursorOverloadedDeclRef(C).second;
+
+ case CXCursor_VariableRef:
+ return getCursorVariableRef(C).second;
+
+ default:
+ // FIXME: Need a way to enumerate all non-reference cases.
+ llvm_unreachable("Missed a reference kind");
+ }
+ }
+
+ if (clang_isExpression(C.kind))
+ return getCursorExpr(C)->getSourceRange();
+
+ if (clang_isStatement(C.kind))
+ return getCursorStmt(C)->getSourceRange();
+
+ if (clang_isAttribute(C.kind))
+ return getCursorAttr(C)->getRange();
+
+ if (C.kind == CXCursor_PreprocessingDirective)
+ return cxcursor::getCursorPreprocessingDirective(C);
+
+ if (C.kind == CXCursor_MacroExpansion) {
+ ASTUnit *TU = getCursorASTUnit(C);
+ SourceRange Range = cxcursor::getCursorMacroExpansion(C)->getSourceRange();
+ return TU->mapRangeFromPreamble(Range);
+ }
+
+ if (C.kind == CXCursor_MacroDefinition) {
+ ASTUnit *TU = getCursorASTUnit(C);
+ SourceRange Range = cxcursor::getCursorMacroDefinition(C)->getSourceRange();
+ return TU->mapRangeFromPreamble(Range);
+ }
+
+ if (C.kind == CXCursor_InclusionDirective) {
+ ASTUnit *TU = getCursorASTUnit(C);
+ SourceRange Range = cxcursor::getCursorInclusionDirective(C)->getSourceRange();
+ return TU->mapRangeFromPreamble(Range);
+ }
+
+ if (C.kind == CXCursor_TranslationUnit) {
+ ASTUnit *TU = getCursorASTUnit(C);
+ FileID MainID = TU->getSourceManager().getMainFileID();
+ SourceLocation Start = TU->getSourceManager().getLocForStartOfFile(MainID);
+ SourceLocation End = TU->getSourceManager().getLocForEndOfFile(MainID);
+ return SourceRange(Start, End);
+ }
+
+ if (clang_isDeclaration(C.kind)) {
+ Decl *D = cxcursor::getCursorDecl(C);
+ if (!D)
+ return SourceRange();
+
+ SourceRange R = D->getSourceRange();
+ // FIXME: Multiple variables declared in a single declaration
+ // currently lack the information needed to correctly determine their
+ // ranges when accounting for the type-specifier. We use context
+ // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
+ // and if so, whether it is the first decl.
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (!cxcursor::isFirstInDeclGroup(C))
+ R.setBegin(VD->getLocation());
+ }
+ return R;
+ }
+ return SourceRange();
+}
+
+/// \brief Retrieves the "raw" cursor extent, which is then extended to include
+/// the decl-specifier-seq for declarations.
+static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr) {
+ if (clang_isDeclaration(C.kind)) {
+ Decl *D = cxcursor::getCursorDecl(C);
+ if (!D)
+ return SourceRange();
+
+ SourceRange R = D->getSourceRange();
+
+ // Adjust the start of the location for declarations preceded by
+ // declaration specifiers.
+ SourceLocation StartLoc;
+ if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
+ if (TypeSourceInfo *TI = DD->getTypeSourceInfo())
+ StartLoc = TI->getTypeLoc().getLocStart();
+ } else if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(D)) {
+ if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())
+ StartLoc = TI->getTypeLoc().getLocStart();
+ }
+
+ if (StartLoc.isValid() && R.getBegin().isValid() &&
+ SrcMgr.isBeforeInTranslationUnit(StartLoc, R.getBegin()))
+ R.setBegin(StartLoc);
+
+ // FIXME: Multiple variables declared in a single declaration
+ // currently lack the information needed to correctly determine their
+ // ranges when accounting for the type-specifier. We use context
+ // stored in the CXCursor to determine if the VarDecl is in a DeclGroup,
+ // and if so, whether it is the first decl.
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (!cxcursor::isFirstInDeclGroup(C))
+ R.setBegin(VD->getLocation());
+ }
+
+ return R;
+ }
+
+ return getRawCursorExtent(C);
+}
+
+extern "C" {
+
+CXSourceRange clang_getCursorExtent(CXCursor C) {
+ SourceRange R = getRawCursorExtent(C);
+ if (R.isInvalid())
+ return clang_getNullRange();
+
+ return cxloc::translateSourceRange(getCursorContext(C), R);
+}
+
+CXCursor clang_getCursorReferenced(CXCursor C) {
+ if (clang_isInvalid(C.kind))
+ return clang_getNullCursor();
+
+ CXTranslationUnit tu = getCursorTU(C);
+ if (clang_isDeclaration(C.kind)) {
+ Decl *D = getCursorDecl(C);
+ if (!D)
+ return clang_getNullCursor();
+ if (UsingDecl *Using = dyn_cast<UsingDecl>(D))
+ return MakeCursorOverloadedDeclRef(Using, D->getLocation(), tu);
+ if (ObjCPropertyImplDecl *PropImpl =dyn_cast<ObjCPropertyImplDecl>(D))
+ if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())
+ return MakeCXCursor(Property, tu);
+
+ return C;
+ }
+
+ if (clang_isExpression(C.kind)) {
+ Expr *E = getCursorExpr(C);
+ Decl *D = getDeclFromExpr(E);
+ if (D) {
+ CXCursor declCursor = MakeCXCursor(D, tu);
+ declCursor = getSelectorIdentifierCursor(getSelectorIdentifierIndex(C),
+ declCursor);
+ return declCursor;
+ }
+
+ if (OverloadExpr *Ovl = dyn_cast_or_null<OverloadExpr>(E))
+ return MakeCursorOverloadedDeclRef(Ovl, tu);
+
+ return clang_getNullCursor();
+ }
+
+ if (clang_isStatement(C.kind)) {
+ Stmt *S = getCursorStmt(C);
+ if (GotoStmt *Goto = dyn_cast_or_null<GotoStmt>(S))
+ if (LabelDecl *label = Goto->getLabel())
+ if (LabelStmt *labelS = label->getStmt())
+ return MakeCXCursor(labelS, getCursorDecl(C), tu);
+
+ return clang_getNullCursor();
+ }
+
+ if (C.kind == CXCursor_MacroExpansion) {
+ if (MacroDefinition *Def = getCursorMacroExpansion(C)->getDefinition())
+ return MakeMacroDefinitionCursor(Def, tu);
+ }
+
+ if (!clang_isReference(C.kind))
+ return clang_getNullCursor();
+
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef:
+ return MakeCXCursor(getCursorObjCSuperClassRef(C).first, tu);
+
+ case CXCursor_ObjCProtocolRef: {
+ ObjCProtocolDecl *Prot = getCursorObjCProtocolRef(C).first;
+ if (ObjCProtocolDecl *Def = Prot->getDefinition())
+ return MakeCXCursor(Def, tu);
+
+ return MakeCXCursor(Prot, tu);
+ }
+
+ case CXCursor_ObjCClassRef: {
+ ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
+ if (ObjCInterfaceDecl *Def = Class->getDefinition())
+ return MakeCXCursor(Def, tu);
+
+ return MakeCXCursor(Class, tu);
+ }
+
+ case CXCursor_TypeRef:
+ return MakeCXCursor(getCursorTypeRef(C).first, tu );
+
+ case CXCursor_TemplateRef:
+ return MakeCXCursor(getCursorTemplateRef(C).first, tu );
+
+ case CXCursor_NamespaceRef:
+ return MakeCXCursor(getCursorNamespaceRef(C).first, tu );
+
+ case CXCursor_MemberRef:
+ return MakeCXCursor(getCursorMemberRef(C).first, tu );
+
+ case CXCursor_CXXBaseSpecifier: {
+ CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C);
+ return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(),
+ tu ));
+ }
+
+ case CXCursor_LabelRef:
+ // FIXME: We end up faking the "parent" declaration here because we
+ // don't want to make CXCursor larger.
+ return MakeCXCursor(getCursorLabelRef(C).first,
+ static_cast<ASTUnit*>(tu->TUData)->getASTContext()
+ .getTranslationUnitDecl(),
+ tu);
+
+ case CXCursor_OverloadedDeclRef:
+ return C;
+
+ case CXCursor_VariableRef:
+ return MakeCXCursor(getCursorVariableRef(C).first, tu);
+
+ default:
+ // We would prefer to enumerate all non-reference cursor kinds here.
+ llvm_unreachable("Unhandled reference cursor kind");
+ }
+}
+
+CXCursor clang_getCursorDefinition(CXCursor C) {
+ if (clang_isInvalid(C.kind))
+ return clang_getNullCursor();
+
+ CXTranslationUnit TU = getCursorTU(C);
+
+ bool WasReference = false;
+ if (clang_isReference(C.kind) || clang_isExpression(C.kind)) {
+ C = clang_getCursorReferenced(C);
+ WasReference = true;
+ }
+
+ if (C.kind == CXCursor_MacroExpansion)
+ return clang_getCursorReferenced(C);
+
+ if (!clang_isDeclaration(C.kind))
+ return clang_getNullCursor();
+
+ Decl *D = getCursorDecl(C);
+ if (!D)
+ return clang_getNullCursor();
+
+ switch (D->getKind()) {
+ // Declaration kinds that don't really separate the notions of
+ // declaration and definition.
+ case Decl::Namespace:
+ case Decl::Typedef:
+ case Decl::TypeAlias:
+ case Decl::TypeAliasTemplate:
+ case Decl::TemplateTypeParm:
+ case Decl::EnumConstant:
+ case Decl::Field:
+ case Decl::IndirectField:
+ case Decl::ObjCIvar:
+ case Decl::ObjCAtDefsField:
+ case Decl::ImplicitParam:
+ case Decl::ParmVar:
+ case Decl::NonTypeTemplateParm:
+ case Decl::TemplateTemplateParm:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCImplementation:
+ case Decl::AccessSpec:
+ case Decl::LinkageSpec:
+ case Decl::ObjCPropertyImpl:
+ case Decl::FileScopeAsm:
+ case Decl::StaticAssert:
+ case Decl::Block:
+ case Decl::Label: // FIXME: Is this right??
+ case Decl::ClassScopeFunctionSpecialization:
+ case Decl::Import:
+ return C;
+
+ // Declaration kinds that don't make any sense here, but are
+ // nonetheless harmless.
+ case Decl::TranslationUnit:
+ break;
+
+ // Declaration kinds for which the definition is not resolvable.
+ case Decl::UnresolvedUsingTypename:
+ case Decl::UnresolvedUsingValue:
+ break;
+
+ case Decl::UsingDirective:
+ return MakeCXCursor(cast<UsingDirectiveDecl>(D)->getNominatedNamespace(),
+ TU);
+
+ case Decl::NamespaceAlias:
+ return MakeCXCursor(cast<NamespaceAliasDecl>(D)->getNamespace(), TU);
+
+ case Decl::Enum:
+ case Decl::Record:
+ case Decl::CXXRecord:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::ClassTemplatePartialSpecialization:
+ if (TagDecl *Def = cast<TagDecl>(D)->getDefinition())
+ return MakeCXCursor(Def, TU);
+ return clang_getNullCursor();
+
+ case Decl::Function:
+ case Decl::CXXMethod:
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion: {
+ const FunctionDecl *Def = 0;
+ if (cast<FunctionDecl>(D)->getBody(Def))
+ return MakeCXCursor(const_cast<FunctionDecl *>(Def), TU);
+ return clang_getNullCursor();
+ }
+
+ case Decl::Var: {
+ // Ask the variable if it has a definition.
+ if (VarDecl *Def = cast<VarDecl>(D)->getDefinition())
+ return MakeCXCursor(Def, TU);
+ return clang_getNullCursor();
+ }
+
+ case Decl::FunctionTemplate: {
+ const FunctionDecl *Def = 0;
+ if (cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->getBody(Def))
+ return MakeCXCursor(Def->getDescribedFunctionTemplate(), TU);
+ return clang_getNullCursor();
+ }
+
+ case Decl::ClassTemplate: {
+ if (RecordDecl *Def = cast<ClassTemplateDecl>(D)->getTemplatedDecl()
+ ->getDefinition())
+ return MakeCXCursor(cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),
+ TU);
+ return clang_getNullCursor();
+ }
+
+ case Decl::Using:
+ return MakeCursorOverloadedDeclRef(cast<UsingDecl>(D),
+ D->getLocation(), TU);
+
+ case Decl::UsingShadow:
+ return clang_getCursorDefinition(
+ MakeCXCursor(cast<UsingShadowDecl>(D)->getTargetDecl(),
+ TU));
+
+ case Decl::ObjCMethod: {
+ ObjCMethodDecl *Method = cast<ObjCMethodDecl>(D);
+ if (Method->isThisDeclarationADefinition())
+ return C;
+
+ // Dig out the method definition in the associated
+ // @implementation, if we have it.
+ // FIXME: The ASTs should make finding the definition easier.
+ if (ObjCInterfaceDecl *Class
+ = dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext()))
+ if (ObjCImplementationDecl *ClassImpl = Class->getImplementation())
+ if (ObjCMethodDecl *Def = ClassImpl->getMethod(Method->getSelector(),
+ Method->isInstanceMethod()))
+ if (Def->isThisDeclarationADefinition())
+ return MakeCXCursor(Def, TU);
+
+ return clang_getNullCursor();
+ }
+
+ case Decl::ObjCCategory:
+ if (ObjCCategoryImplDecl *Impl
+ = cast<ObjCCategoryDecl>(D)->getImplementation())
+ return MakeCXCursor(Impl, TU);
+ return clang_getNullCursor();
+
+ case Decl::ObjCProtocol:
+ if (ObjCProtocolDecl *Def = cast<ObjCProtocolDecl>(D)->getDefinition())
+ return MakeCXCursor(Def, TU);
+ return clang_getNullCursor();
+
+ case Decl::ObjCInterface: {
+ // There are two notions of a "definition" for an Objective-C
+ // class: the interface and its implementation. When we resolved a
+ // reference to an Objective-C class, produce the @interface as
+ // the definition; when we were provided with the interface,
+ // produce the @implementation as the definition.
+ ObjCInterfaceDecl *IFace = cast<ObjCInterfaceDecl>(D);
+ if (WasReference) {
+ if (ObjCInterfaceDecl *Def = IFace->getDefinition())
+ return MakeCXCursor(Def, TU);
+ } else if (ObjCImplementationDecl *Impl = IFace->getImplementation())
+ return MakeCXCursor(Impl, TU);
+ return clang_getNullCursor();
+ }
+
+ case Decl::ObjCProperty:
+ // FIXME: We don't really know where to find the
+ // ObjCPropertyImplDecls that implement this property.
+ return clang_getNullCursor();
+
+ case Decl::ObjCCompatibleAlias:
+ if (ObjCInterfaceDecl *Class
+ = cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())
+ if (ObjCInterfaceDecl *Def = Class->getDefinition())
+ return MakeCXCursor(Def, TU);
+
+ return clang_getNullCursor();
+
+ case Decl::Friend:
+ if (NamedDecl *Friend = cast<FriendDecl>(D)->getFriendDecl())
+ return clang_getCursorDefinition(MakeCXCursor(Friend, TU));
+ return clang_getNullCursor();
+
+ case Decl::FriendTemplate:
+ if (NamedDecl *Friend = cast<FriendTemplateDecl>(D)->getFriendDecl())
+ return clang_getCursorDefinition(MakeCXCursor(Friend, TU));
+ return clang_getNullCursor();
+ }
+
+ return clang_getNullCursor();
+}
+
+unsigned clang_isCursorDefinition(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ return clang_getCursorDefinition(C) == C;
+}
+
+CXCursor clang_getCanonicalCursor(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return C;
+
+ if (Decl *D = getCursorDecl(C)) {
+ if (ObjCCategoryImplDecl *CatImplD = dyn_cast<ObjCCategoryImplDecl>(D))
+ if (ObjCCategoryDecl *CatD = CatImplD->getCategoryDecl())
+ return MakeCXCursor(CatD, getCursorTU(C));
+
+ if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D))
+ if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
+ return MakeCXCursor(IFD, getCursorTU(C));
+
+ return MakeCXCursor(D->getCanonicalDecl(), getCursorTU(C));
+ }
+
+ return C;
+}
+
+int clang_Cursor_getObjCSelectorIndex(CXCursor cursor) {
+ return cxcursor::getSelectorIdentifierIndexAndLoc(cursor).first;
+}
+
+unsigned clang_getNumOverloadedDecls(CXCursor C) {
+ if (C.kind != CXCursor_OverloadedDeclRef)
+ return 0;
+
+ OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;
+ if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>())
+ return E->getNumDecls();
+
+ if (OverloadedTemplateStorage *S
+ = Storage.dyn_cast<OverloadedTemplateStorage*>())
+ return S->size();
+
+ Decl *D = Storage.get<Decl*>();
+ if (UsingDecl *Using = dyn_cast<UsingDecl>(D))
+ return Using->shadow_size();
+
+ return 0;
+}
+
+CXCursor clang_getOverloadedDecl(CXCursor cursor, unsigned index) {
+ if (cursor.kind != CXCursor_OverloadedDeclRef)
+ return clang_getNullCursor();
+
+ if (index >= clang_getNumOverloadedDecls(cursor))
+ return clang_getNullCursor();
+
+ CXTranslationUnit TU = getCursorTU(cursor);
+ OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(cursor).first;
+ if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>())
+ return MakeCXCursor(E->decls_begin()[index], TU);
+
+ if (OverloadedTemplateStorage *S
+ = Storage.dyn_cast<OverloadedTemplateStorage*>())
+ return MakeCXCursor(S->begin()[index], TU);
+
+ Decl *D = Storage.get<Decl*>();
+ if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) {
+ // FIXME: This is, unfortunately, linear time.
+ UsingDecl::shadow_iterator Pos = Using->shadow_begin();
+ std::advance(Pos, index);
+ return MakeCXCursor(cast<UsingShadowDecl>(*Pos)->getTargetDecl(), TU);
+ }
+
+ return clang_getNullCursor();
+}
+
+void clang_getDefinitionSpellingAndExtent(CXCursor C,
+ const char **startBuf,
+ const char **endBuf,
+ unsigned *startLine,
+ unsigned *startColumn,
+ unsigned *endLine,
+ unsigned *endColumn) {
+ assert(getCursorDecl(C) && "CXCursor has null decl");
+ NamedDecl *ND = static_cast<NamedDecl *>(getCursorDecl(C));
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
+ CompoundStmt *Body = dyn_cast<CompoundStmt>(FD->getBody());
+
+ SourceManager &SM = FD->getASTContext().getSourceManager();
+ *startBuf = SM.getCharacterData(Body->getLBracLoc());
+ *endBuf = SM.getCharacterData(Body->getRBracLoc());
+ *startLine = SM.getSpellingLineNumber(Body->getLBracLoc());
+ *startColumn = SM.getSpellingColumnNumber(Body->getLBracLoc());
+ *endLine = SM.getSpellingLineNumber(Body->getRBracLoc());
+ *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());
+}
+
+
+CXSourceRange clang_getCursorReferenceNameRange(CXCursor C, unsigned NameFlags,
+ unsigned PieceIndex) {
+ RefNamePieces Pieces;
+
+ switch (C.kind) {
+ case CXCursor_MemberRefExpr:
+ if (MemberExpr *E = dyn_cast<MemberExpr>(getCursorExpr(C)))
+ Pieces = buildPieces(NameFlags, true, E->getMemberNameInfo(),
+ E->getQualifierLoc().getSourceRange());
+ break;
+
+ case CXCursor_DeclRefExpr:
+ if (DeclRefExpr *E = dyn_cast<DeclRefExpr>(getCursorExpr(C)))
+ Pieces = buildPieces(NameFlags, false, E->getNameInfo(),
+ E->getQualifierLoc().getSourceRange(),
+ E->getOptionalExplicitTemplateArgs());
+ break;
+
+ case CXCursor_CallExpr:
+ if (CXXOperatorCallExpr *OCE =
+ dyn_cast<CXXOperatorCallExpr>(getCursorExpr(C))) {
+ Expr *Callee = OCE->getCallee();
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Callee))
+ Callee = ICE->getSubExpr();
+
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee))
+ Pieces = buildPieces(NameFlags, false, DRE->getNameInfo(),
+ DRE->getQualifierLoc().getSourceRange());
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (Pieces.empty()) {
+ if (PieceIndex == 0)
+ return clang_getCursorExtent(C);
+ } else if (PieceIndex < Pieces.size()) {
+ SourceRange R = Pieces[PieceIndex];
+ if (R.isValid())
+ return cxloc::translateSourceRange(getCursorContext(C), R);
+ }
+
+ return clang_getNullRange();
+}
+
+void clang_enableStackTraces(void) {
+ llvm::sys::PrintStackTraceOnErrorSignal();
+}
+
+void clang_executeOnThread(void (*fn)(void*), void *user_data,
+ unsigned stack_size) {
+ llvm::llvm_execute_on_thread(fn, user_data, stack_size);
+}
+
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// Token-based Operations.
+//===----------------------------------------------------------------------===//
+
+/* CXToken layout:
+ * int_data[0]: a CXTokenKind
+ * int_data[1]: starting token location
+ * int_data[2]: token length
+ * int_data[3]: reserved
+ * ptr_data: for identifiers and keywords, an IdentifierInfo*.
+ * otherwise unused.
+ */
+extern "C" {
+
+CXTokenKind clang_getTokenKind(CXToken CXTok) {
+ return static_cast<CXTokenKind>(CXTok.int_data[0]);
+}
+
+CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) {
+ switch (clang_getTokenKind(CXTok)) {
+ case CXToken_Identifier:
+ case CXToken_Keyword:
+ // We know we have an IdentifierInfo*, so use that.
+ return createCXString(static_cast<IdentifierInfo *>(CXTok.ptr_data)
+ ->getNameStart());
+
+ case CXToken_Literal: {
+ // We have stashed the starting pointer in the ptr_data field. Use it.
+ const char *Text = static_cast<const char *>(CXTok.ptr_data);
+ return createCXString(StringRef(Text, CXTok.int_data[2]));
+ }
+
+ case CXToken_Punctuation:
+ case CXToken_Comment:
+ break;
+ }
+
+ // We have to find the starting buffer pointer the hard way, by
+ // deconstructing the source location.
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
+ if (!CXXUnit)
+ return createCXString("");
+
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]);
+ std::pair<FileID, unsigned> LocInfo
+ = CXXUnit->getSourceManager().getDecomposedSpellingLoc(Loc);
+ bool Invalid = false;
+ StringRef Buffer
+ = CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid);
+ if (Invalid)
+ return createCXString("");
+
+ return createCXString(Buffer.substr(LocInfo.second, CXTok.int_data[2]));
+}
+
+CXSourceLocation clang_getTokenLocation(CXTranslationUnit TU, CXToken CXTok) {
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
+ if (!CXXUnit)
+ return clang_getNullLocation();
+
+ return cxloc::translateSourceLocation(CXXUnit->getASTContext(),
+ SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
+}
+
+CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) {
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
+ if (!CXXUnit)
+ return clang_getNullRange();
+
+ return cxloc::translateSourceRange(CXXUnit->getASTContext(),
+ SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
+}
+
+static void getTokens(ASTUnit *CXXUnit, SourceRange Range,
+ SmallVectorImpl<CXToken> &CXTokens) {
+ SourceManager &SourceMgr = CXXUnit->getSourceManager();
+ std::pair<FileID, unsigned> BeginLocInfo
+ = SourceMgr.getDecomposedLoc(Range.getBegin());
+ std::pair<FileID, unsigned> EndLocInfo
+ = SourceMgr.getDecomposedLoc(Range.getEnd());
+
+ // Cannot tokenize across files.
+ if (BeginLocInfo.first != EndLocInfo.first)
+ return;
+
+ // Create a lexer
+ bool Invalid = false;
+ StringRef Buffer
+ = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid);
+ if (Invalid)
+ return;
+
+ Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
+ CXXUnit->getASTContext().getLangOpts(),
+ Buffer.begin(), Buffer.data() + BeginLocInfo.second, Buffer.end());
+ Lex.SetCommentRetentionState(true);
+
+ // Lex tokens until we hit the end of the range.
+ const char *EffectiveBufferEnd = Buffer.data() + EndLocInfo.second;
+ Token Tok;
+ bool previousWasAt = false;
+ do {
+ // Lex the next token
+ Lex.LexFromRawLexer(Tok);
+ if (Tok.is(tok::eof))
+ break;
+
+ // Initialize the CXToken.
+ CXToken CXTok;
+
+ // - Common fields
+ CXTok.int_data[1] = Tok.getLocation().getRawEncoding();
+ CXTok.int_data[2] = Tok.getLength();
+ CXTok.int_data[3] = 0;
+
+ // - Kind-specific fields
+ if (Tok.isLiteral()) {
+ CXTok.int_data[0] = CXToken_Literal;
+ CXTok.ptr_data = (void *)Tok.getLiteralData();
+ } else if (Tok.is(tok::raw_identifier)) {
+ // Lookup the identifier to determine whether we have a keyword.
+ IdentifierInfo *II
+ = CXXUnit->getPreprocessor().LookUpIdentifierInfo(Tok);
+
+ if ((II->getObjCKeywordID() != tok::objc_not_keyword) && previousWasAt) {
+ CXTok.int_data[0] = CXToken_Keyword;
+ }
+ else {
+ CXTok.int_data[0] = Tok.is(tok::identifier)
+ ? CXToken_Identifier
+ : CXToken_Keyword;
+ }
+ CXTok.ptr_data = II;
+ } else if (Tok.is(tok::comment)) {
+ CXTok.int_data[0] = CXToken_Comment;
+ CXTok.ptr_data = 0;
+ } else {
+ CXTok.int_data[0] = CXToken_Punctuation;
+ CXTok.ptr_data = 0;
+ }
+ CXTokens.push_back(CXTok);
+ previousWasAt = Tok.is(tok::at);
+ } while (Lex.getBufferLocation() <= EffectiveBufferEnd);
+}
+
+void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
+ CXToken **Tokens, unsigned *NumTokens) {
+ if (Tokens)
+ *Tokens = 0;
+ if (NumTokens)
+ *NumTokens = 0;
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
+ if (!CXXUnit || !Tokens || !NumTokens)
+ return;
+
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ SourceRange R = cxloc::translateCXSourceRange(Range);
+ if (R.isInvalid())
+ return;
+
+ SmallVector<CXToken, 32> CXTokens;
+ getTokens(CXXUnit, R, CXTokens);
+
+ if (CXTokens.empty())
+ return;
+
+ *Tokens = (CXToken *)malloc(sizeof(CXToken) * CXTokens.size());
+ memmove(*Tokens, CXTokens.data(), sizeof(CXToken) * CXTokens.size());
+ *NumTokens = CXTokens.size();
+}
+
+void clang_disposeTokens(CXTranslationUnit TU,
+ CXToken *Tokens, unsigned NumTokens) {
+ free(Tokens);
+}
+
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// Token annotation APIs.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::DenseMap<unsigned, CXCursor> AnnotateTokensData;
+static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
+ CXCursor parent,
+ CXClientData client_data);
+static bool AnnotateTokensPostChildrenVisitor(CXCursor cursor,
+ CXClientData client_data);
+
+namespace {
+class AnnotateTokensWorker {
+ AnnotateTokensData &Annotated;
+ CXToken *Tokens;
+ CXCursor *Cursors;
+ unsigned NumTokens;
+ unsigned TokIdx;
+ unsigned PreprocessingTokIdx;
+ CursorVisitor AnnotateVis;
+ SourceManager &SrcMgr;
+ bool HasContextSensitiveKeywords;
+
+ struct PostChildrenInfo {
+ CXCursor Cursor;
+ SourceRange CursorRange;
+ unsigned BeforeChildrenTokenIdx;
+ };
+ llvm::SmallVector<PostChildrenInfo, 8> PostChildrenInfos;
+
+ bool MoreTokens() const { return TokIdx < NumTokens; }
+ unsigned NextToken() const { return TokIdx; }
+ void AdvanceToken() { ++TokIdx; }
+ SourceLocation GetTokenLoc(unsigned tokI) {
+ return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[1]);
+ }
+ bool isFunctionMacroToken(unsigned tokI) const {
+ return Tokens[tokI].int_data[3] != 0;
+ }
+ SourceLocation getFunctionMacroTokenLoc(unsigned tokI) const {
+ return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[3]);
+ }
+
+ void annotateAndAdvanceTokens(CXCursor, RangeComparisonResult, SourceRange);
+ void annotateAndAdvanceFunctionMacroTokens(CXCursor, RangeComparisonResult,
+ SourceRange);
+
+public:
+ AnnotateTokensWorker(AnnotateTokensData &annotated,
+ CXToken *tokens, CXCursor *cursors, unsigned numTokens,
+ CXTranslationUnit tu, SourceRange RegionOfInterest)
+ : Annotated(annotated), Tokens(tokens), Cursors(cursors),
+ NumTokens(numTokens), TokIdx(0), PreprocessingTokIdx(0),
+ AnnotateVis(tu,
+ AnnotateTokensVisitor, this,
+ /*VisitPreprocessorLast=*/true,
+ /*VisitIncludedEntities=*/false,
+ RegionOfInterest,
+ /*VisitDeclsOnly=*/false,
+ AnnotateTokensPostChildrenVisitor),
+ SrcMgr(static_cast<ASTUnit*>(tu->TUData)->getSourceManager()),
+ HasContextSensitiveKeywords(false) { }
+
+ void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); }
+ enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent);
+ bool postVisitChildren(CXCursor cursor);
+ void AnnotateTokens();
+
+ /// \brief Determine whether the annotator saw any cursors that have
+ /// context-sensitive keywords.
+ bool hasContextSensitiveKeywords() const {
+ return HasContextSensitiveKeywords;
+ }
+
+ ~AnnotateTokensWorker() {
+ assert(PostChildrenInfos.empty());
+ }
+};
+}
+
+void AnnotateTokensWorker::AnnotateTokens() {
+ // Walk the AST within the region of interest, annotating tokens
+ // along the way.
+ AnnotateVis.visitFileRegion();
+
+ for (unsigned I = 0 ; I < TokIdx ; ++I) {
+ AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]);
+ if (Pos != Annotated.end() && !clang_isPreprocessing(Cursors[I].kind))
+ Cursors[I] = Pos->second;
+ }
+
+ // Finish up annotating any tokens left.
+ if (!MoreTokens())
+ return;
+
+ const CXCursor &C = clang_getNullCursor();
+ for (unsigned I = TokIdx ; I < NumTokens ; ++I) {
+ if (I < PreprocessingTokIdx && clang_isPreprocessing(Cursors[I].kind))
+ continue;
+
+ AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]);
+ Cursors[I] = (Pos == Annotated.end()) ? C : Pos->second;
+ }
+}
+
+/// \brief It annotates and advances tokens with a cursor until the comparison
+//// between the cursor location and the source range is the same as
+/// \arg compResult.
+///
+/// Pass RangeBefore to annotate tokens with a cursor until a range is reached.
+/// Pass RangeOverlap to annotate tokens inside a range.
+void AnnotateTokensWorker::annotateAndAdvanceTokens(CXCursor updateC,
+ RangeComparisonResult compResult,
+ SourceRange range) {
+ while (MoreTokens()) {
+ const unsigned I = NextToken();
+ if (isFunctionMacroToken(I))
+ return annotateAndAdvanceFunctionMacroTokens(updateC, compResult, range);
+
+ SourceLocation TokLoc = GetTokenLoc(I);
+ if (LocationCompare(SrcMgr, TokLoc, range) == compResult) {
+ Cursors[I] = updateC;
+ AdvanceToken();
+ continue;
+ }
+ break;
+ }
+}
+
+/// \brief Special annotation handling for macro argument tokens.
+void AnnotateTokensWorker::annotateAndAdvanceFunctionMacroTokens(
+ CXCursor updateC,
+ RangeComparisonResult compResult,
+ SourceRange range) {
+ assert(MoreTokens());
+ assert(isFunctionMacroToken(NextToken()) &&
+ "Should be called only for macro arg tokens");
+
+ // This works differently than annotateAndAdvanceTokens; because expanded
+ // macro arguments can have arbitrary translation-unit source order, we do not
+ // advance the token index one by one until a token fails the range test.
+ // We only advance once past all of the macro arg tokens if all of them
+ // pass the range test. If one of them fails we keep the token index pointing
+ // at the start of the macro arg tokens so that the failing token will be
+ // annotated by a subsequent annotation try.
+
+ bool atLeastOneCompFail = false;
+
+ unsigned I = NextToken();
+ for (; I < NumTokens && isFunctionMacroToken(I); ++I) {
+ SourceLocation TokLoc = getFunctionMacroTokenLoc(I);
+ if (TokLoc.isFileID())
+ continue; // not macro arg token, it's parens or comma.
+ if (LocationCompare(SrcMgr, TokLoc, range) == compResult) {
+ if (clang_isInvalid(clang_getCursorKind(Cursors[I])))
+ Cursors[I] = updateC;
+ } else
+ atLeastOneCompFail = true;
+ }
+
+ if (!atLeastOneCompFail)
+ TokIdx = I; // All of the tokens were handled, advance beyond all of them.
+}
+
+enum CXChildVisitResult
+AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
+ CXSourceLocation Loc = clang_getCursorLocation(cursor);
+ SourceRange cursorRange = getRawCursorExtent(cursor);
+ if (cursorRange.isInvalid())
+ return CXChildVisit_Recurse;
+
+ if (!HasContextSensitiveKeywords) {
+ // Objective-C properties can have context-sensitive keywords.
+ if (cursor.kind == CXCursor_ObjCPropertyDecl) {
+ if (ObjCPropertyDecl *Property
+ = dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(cursor)))
+ HasContextSensitiveKeywords = Property->getPropertyAttributesAsWritten() != 0;
+ }
+ // Objective-C methods can have context-sensitive keywords.
+ else if (cursor.kind == CXCursor_ObjCInstanceMethodDecl ||
+ cursor.kind == CXCursor_ObjCClassMethodDecl) {
+ if (ObjCMethodDecl *Method
+ = dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {
+ if (Method->getObjCDeclQualifier())
+ HasContextSensitiveKeywords = true;
+ else {
+ for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
+ P != PEnd; ++P) {
+ if ((*P)->getObjCDeclQualifier()) {
+ HasContextSensitiveKeywords = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ // C++ methods can have context-sensitive keywords.
+ else if (cursor.kind == CXCursor_CXXMethod) {
+ if (CXXMethodDecl *Method
+ = dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(cursor))) {
+ if (Method->hasAttr<FinalAttr>() || Method->hasAttr<OverrideAttr>())
+ HasContextSensitiveKeywords = true;
+ }
+ }
+ // C++ classes can have context-sensitive keywords.
+ else if (cursor.kind == CXCursor_StructDecl ||
+ cursor.kind == CXCursor_ClassDecl ||
+ cursor.kind == CXCursor_ClassTemplate ||
+ cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {
+ if (Decl *D = getCursorDecl(cursor))
+ if (D->hasAttr<FinalAttr>())
+ HasContextSensitiveKeywords = true;
+ }
+ }
+
+ if (clang_isPreprocessing(cursor.kind)) {
+ // Items in the preprocessing record are kept separate from items in
+ // declarations, so we keep a separate token index.
+ unsigned SavedTokIdx = TokIdx;
+ TokIdx = PreprocessingTokIdx;
+
+ // Skip tokens up until we catch up to the beginning of the preprocessing
+ // entry.
+ while (MoreTokens()) {
+ const unsigned I = NextToken();
+ SourceLocation TokLoc = GetTokenLoc(I);
+ switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
+ case RangeBefore:
+ AdvanceToken();
+ continue;
+ case RangeAfter:
+ case RangeOverlap:
+ break;
+ }
+ break;
+ }
+
+ // Look at all of the tokens within this range.
+ while (MoreTokens()) {
+ const unsigned I = NextToken();
+ SourceLocation TokLoc = GetTokenLoc(I);
+ switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) {
+ case RangeBefore:
+ llvm_unreachable("Infeasible");
+ case RangeAfter:
+ break;
+ case RangeOverlap:
+ Cursors[I] = cursor;
+ AdvanceToken();
+ // For macro expansions, just note where the beginning of the macro
+ // expansion occurs.
+ if (cursor.kind == CXCursor_MacroExpansion)
+ break;
+ continue;
+ }
+ break;
+ }
+
+ // Save the preprocessing token index; restore the non-preprocessing
+ // token index.
+ PreprocessingTokIdx = TokIdx;
+ TokIdx = SavedTokIdx;
+ return CXChildVisit_Recurse;
+ }
+
+ if (cursorRange.isInvalid())
+ return CXChildVisit_Continue;
+
+ SourceLocation L = SourceLocation::getFromRawEncoding(Loc.int_data);
+
+ // Adjust the annotated range based specific declarations.
+ const enum CXCursorKind cursorK = clang_getCursorKind(cursor);
+ if (clang_isDeclaration(cursorK)) {
+ Decl *D = cxcursor::getCursorDecl(cursor);
+
+ SourceLocation StartLoc;
+ if (const DeclaratorDecl *DD = dyn_cast_or_null<DeclaratorDecl>(D)) {
+ if (TypeSourceInfo *TI = DD->getTypeSourceInfo())
+ StartLoc = TI->getTypeLoc().getLocStart();
+ } else if (TypedefDecl *Typedef = dyn_cast_or_null<TypedefDecl>(D)) {
+ if (TypeSourceInfo *TI = Typedef->getTypeSourceInfo())
+ StartLoc = TI->getTypeLoc().getLocStart();
+ }
+
+ if (StartLoc.isValid() && L.isValid() &&
+ SrcMgr.isBeforeInTranslationUnit(StartLoc, L))
+ cursorRange.setBegin(StartLoc);
+ }
+
+ // If the location of the cursor occurs within a macro instantiation, record
+ // the spelling location of the cursor in our annotation map. We can then
+ // paper over the token labelings during a post-processing step to try and
+ // get cursor mappings for tokens that are the *arguments* of a macro
+ // instantiation.
+ if (L.isMacroID()) {
+ unsigned rawEncoding = SrcMgr.getSpellingLoc(L).getRawEncoding();
+ // Only invalidate the old annotation if it isn't part of a preprocessing
+ // directive. Here we assume that the default construction of CXCursor
+ // results in CXCursor.kind being an initialized value (i.e., 0). If
+ // this isn't the case, we can fix by doing lookup + insertion.
+
+ CXCursor &oldC = Annotated[rawEncoding];
+ if (!clang_isPreprocessing(oldC.kind))
+ oldC = cursor;
+ }
+
+ const enum CXCursorKind K = clang_getCursorKind(parent);
+ const CXCursor updateC =
+ (clang_isInvalid(K) || K == CXCursor_TranslationUnit)
+ ? clang_getNullCursor() : parent;
+
+ annotateAndAdvanceTokens(updateC, RangeBefore, cursorRange);
+
+ // Avoid having the cursor of an expression "overwrite" the annotation of the
+ // variable declaration that it belongs to.
+ // This can happen for C++ constructor expressions whose range generally
+ // include the variable declaration, e.g.:
+ // MyCXXClass foo; // Make sure we don't annotate 'foo' as a CallExpr cursor.
+ if (clang_isExpression(cursorK)) {
+ Expr *E = getCursorExpr(cursor);
+ if (Decl *D = getCursorParentDecl(cursor)) {
+ const unsigned I = NextToken();
+ if (E->getLocStart().isValid() && D->getLocation().isValid() &&
+ E->getLocStart() == D->getLocation() &&
+ E->getLocStart() == GetTokenLoc(I)) {
+ Cursors[I] = updateC;
+ AdvanceToken();
+ }
+ }
+ }
+
+ // Before recursing into the children keep some state that we are going
+ // to use in the AnnotateTokensWorker::postVisitChildren callback to do some
+ // extra work after the child nodes are visited.
+ // Note that we don't call VisitChildren here to avoid traversing statements
+ // code-recursively which can blow the stack.
+
+ PostChildrenInfo Info;
+ Info.Cursor = cursor;
+ Info.CursorRange = cursorRange;
+ Info.BeforeChildrenTokenIdx = NextToken();
+ PostChildrenInfos.push_back(Info);
+
+ return CXChildVisit_Recurse;
+}
+
+bool AnnotateTokensWorker::postVisitChildren(CXCursor cursor) {
+ if (PostChildrenInfos.empty())
+ return false;
+ const PostChildrenInfo &Info = PostChildrenInfos.back();
+ if (!clang_equalCursors(Info.Cursor, cursor))
+ return false;
+
+ const unsigned BeforeChildren = Info.BeforeChildrenTokenIdx;
+ const unsigned AfterChildren = NextToken();
+ SourceRange cursorRange = Info.CursorRange;
+
+ // Scan the tokens that are at the end of the cursor, but are not captured
+ // but the child cursors.
+ annotateAndAdvanceTokens(cursor, RangeOverlap, cursorRange);
+
+ // Scan the tokens that are at the beginning of the cursor, but are not
+ // capture by the child cursors.
+ for (unsigned I = BeforeChildren; I != AfterChildren; ++I) {
+ if (!clang_isInvalid(clang_getCursorKind(Cursors[I])))
+ break;
+
+ Cursors[I] = cursor;
+ }
+
+ PostChildrenInfos.pop_back();
+ return false;
+}
+
+static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
+ CXCursor parent,
+ CXClientData client_data) {
+ return static_cast<AnnotateTokensWorker*>(client_data)->Visit(cursor, parent);
+}
+
+static bool AnnotateTokensPostChildrenVisitor(CXCursor cursor,
+ CXClientData client_data) {
+ return static_cast<AnnotateTokensWorker*>(client_data)->
+ postVisitChildren(cursor);
+}
+
+namespace {
+
+/// \brief Uses the macro expansions in the preprocessing record to find
+/// and mark tokens that are macro arguments. This info is used by the
+/// AnnotateTokensWorker.
+class MarkMacroArgTokensVisitor {
+ SourceManager &SM;
+ CXToken *Tokens;
+ unsigned NumTokens;
+ unsigned CurIdx;
+
+public:
+ MarkMacroArgTokensVisitor(SourceManager &SM,
+ CXToken *tokens, unsigned numTokens)
+ : SM(SM), Tokens(tokens), NumTokens(numTokens), CurIdx(0) { }
+
+ CXChildVisitResult visit(CXCursor cursor, CXCursor parent) {
+ if (cursor.kind != CXCursor_MacroExpansion)
+ return CXChildVisit_Continue;
+
+ SourceRange macroRange = getCursorMacroExpansion(cursor)->getSourceRange();
+ if (macroRange.getBegin() == macroRange.getEnd())
+ return CXChildVisit_Continue; // it's not a function macro.
+
+ for (; CurIdx < NumTokens; ++CurIdx) {
+ if (!SM.isBeforeInTranslationUnit(getTokenLoc(CurIdx),
+ macroRange.getBegin()))
+ break;
+ }
+
+ if (CurIdx == NumTokens)
+ return CXChildVisit_Break;
+
+ for (; CurIdx < NumTokens; ++CurIdx) {
+ SourceLocation tokLoc = getTokenLoc(CurIdx);
+ if (!SM.isBeforeInTranslationUnit(tokLoc, macroRange.getEnd()))
+ break;
+
+ setFunctionMacroTokenLoc(CurIdx, SM.getMacroArgExpandedLocation(tokLoc));
+ }
+
+ if (CurIdx == NumTokens)
+ return CXChildVisit_Break;
+
+ return CXChildVisit_Continue;
+ }
+
+private:
+ SourceLocation getTokenLoc(unsigned tokI) {
+ return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[1]);
+ }
+
+ void setFunctionMacroTokenLoc(unsigned tokI, SourceLocation loc) {
+ // The third field is reserved and currently not used. Use it here
+ // to mark macro arg expanded tokens with their expanded locations.
+ Tokens[tokI].int_data[3] = loc.getRawEncoding();
+ }
+};
+
+} // end anonymous namespace
+
+static CXChildVisitResult
+MarkMacroArgTokensVisitorDelegate(CXCursor cursor, CXCursor parent,
+ CXClientData client_data) {
+ return static_cast<MarkMacroArgTokensVisitor*>(client_data)->visit(cursor,
+ parent);
+}
+
+namespace {
+ struct clang_annotateTokens_Data {
+ CXTranslationUnit TU;
+ ASTUnit *CXXUnit;
+ CXToken *Tokens;
+ unsigned NumTokens;
+ CXCursor *Cursors;
+ };
+}
+
+static void annotatePreprocessorTokens(CXTranslationUnit TU,
+ SourceRange RegionOfInterest,
+ AnnotateTokensData &Annotated) {
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
+
+ SourceManager &SourceMgr = CXXUnit->getSourceManager();
+ std::pair<FileID, unsigned> BeginLocInfo
+ = SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin());
+ std::pair<FileID, unsigned> EndLocInfo
+ = SourceMgr.getDecomposedLoc(RegionOfInterest.getEnd());
+
+ if (BeginLocInfo.first != EndLocInfo.first)
+ return;
+
+ StringRef Buffer;
+ bool Invalid = false;
+ Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid);
+ if (Buffer.empty() || Invalid)
+ return;
+
+ Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
+ CXXUnit->getASTContext().getLangOpts(),
+ Buffer.begin(), Buffer.data() + BeginLocInfo.second,
+ Buffer.end());
+ Lex.SetCommentRetentionState(true);
+
+ // Lex tokens in raw mode until we hit the end of the range, to avoid
+ // entering #includes or expanding macros.
+ while (true) {
+ Token Tok;
+ Lex.LexFromRawLexer(Tok);
+
+ reprocess:
+ if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
+ // We have found a preprocessing directive. Gobble it up so that we
+ // don't see it while preprocessing these tokens later, but keep track
+ // of all of the token locations inside this preprocessing directive so
+ // that we can annotate them appropriately.
+ //
+ // FIXME: Some simple tests here could identify macro definitions and
+ // #undefs, to provide specific cursor kinds for those.
+ SmallVector<SourceLocation, 32> Locations;
+ do {
+ Locations.push_back(Tok.getLocation());
+ Lex.LexFromRawLexer(Tok);
+ } while (!Tok.isAtStartOfLine() && !Tok.is(tok::eof));
+
+ using namespace cxcursor;
+ CXCursor Cursor
+ = MakePreprocessingDirectiveCursor(SourceRange(Locations.front(),
+ Locations.back()),
+ TU);
+ for (unsigned I = 0, N = Locations.size(); I != N; ++I) {
+ Annotated[Locations[I].getRawEncoding()] = Cursor;
+ }
+
+ if (Tok.isAtStartOfLine())
+ goto reprocess;
+
+ continue;
+ }
+
+ if (Tok.is(tok::eof))
+ break;
+ }
+}
+
+// This gets run a separate thread to avoid stack blowout.
+static void clang_annotateTokensImpl(void *UserData) {
+ CXTranslationUnit TU = ((clang_annotateTokens_Data*)UserData)->TU;
+ ASTUnit *CXXUnit = ((clang_annotateTokens_Data*)UserData)->CXXUnit;
+ CXToken *Tokens = ((clang_annotateTokens_Data*)UserData)->Tokens;
+ const unsigned NumTokens = ((clang_annotateTokens_Data*)UserData)->NumTokens;
+ CXCursor *Cursors = ((clang_annotateTokens_Data*)UserData)->Cursors;
+
+ CIndexer *CXXIdx = (CIndexer*)TU->CIdx;
+ if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
+ setThreadBackgroundPriority();
+
+ // Determine the region of interest, which contains all of the tokens.
+ SourceRange RegionOfInterest;
+ RegionOfInterest.setBegin(
+ cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0])));
+ RegionOfInterest.setEnd(
+ cxloc::translateSourceLocation(clang_getTokenLocation(TU,
+ Tokens[NumTokens-1])));
+
+ // A mapping from the source locations found when re-lexing or traversing the
+ // region of interest to the corresponding cursors.
+ AnnotateTokensData Annotated;
+
+ // Relex the tokens within the source range to look for preprocessing
+ // directives.
+ annotatePreprocessorTokens(TU, RegionOfInterest, Annotated);
+
+ if (CXXUnit->getPreprocessor().getPreprocessingRecord()) {
+ // Search and mark tokens that are macro argument expansions.
+ MarkMacroArgTokensVisitor Visitor(CXXUnit->getSourceManager(),
+ Tokens, NumTokens);
+ CursorVisitor MacroArgMarker(TU,
+ MarkMacroArgTokensVisitorDelegate, &Visitor,
+ /*VisitPreprocessorLast=*/true,
+ /*VisitIncludedEntities=*/false,
+ RegionOfInterest);
+ MacroArgMarker.visitPreprocessedEntitiesInRegion();
+ }
+
+ // Annotate all of the source locations in the region of interest that map to
+ // a specific cursor.
+ AnnotateTokensWorker W(Annotated, Tokens, Cursors, NumTokens,
+ TU, RegionOfInterest);
+
+ // FIXME: We use a ridiculous stack size here because the data-recursion
+ // algorithm uses a large stack frame than the non-data recursive version,
+ // and AnnotationTokensWorker currently transforms the data-recursion
+ // algorithm back into a traditional recursion by explicitly calling
+ // VisitChildren(). We will need to remove this explicit recursive call.
+ W.AnnotateTokens();
+
+ // If we ran into any entities that involve context-sensitive keywords,
+ // take another pass through the tokens to mark them as such.
+ if (W.hasContextSensitiveKeywords()) {
+ for (unsigned I = 0; I != NumTokens; ++I) {
+ if (clang_getTokenKind(Tokens[I]) != CXToken_Identifier)
+ continue;
+
+ if (Cursors[I].kind == CXCursor_ObjCPropertyDecl) {
+ IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
+ if (ObjCPropertyDecl *Property
+ = dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(Cursors[I]))) {
+ if (Property->getPropertyAttributesAsWritten() != 0 &&
+ llvm::StringSwitch<bool>(II->getName())
+ .Case("readonly", true)
+ .Case("assign", true)
+ .Case("unsafe_unretained", true)
+ .Case("readwrite", true)
+ .Case("retain", true)
+ .Case("copy", true)
+ .Case("nonatomic", true)
+ .Case("atomic", true)
+ .Case("getter", true)
+ .Case("setter", true)
+ .Case("strong", true)
+ .Case("weak", true)
+ .Default(false))
+ Tokens[I].int_data[0] = CXToken_Keyword;
+ }
+ continue;
+ }
+
+ if (Cursors[I].kind == CXCursor_ObjCInstanceMethodDecl ||
+ Cursors[I].kind == CXCursor_ObjCClassMethodDecl) {
+ IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
+ if (llvm::StringSwitch<bool>(II->getName())
+ .Case("in", true)
+ .Case("out", true)
+ .Case("inout", true)
+ .Case("oneway", true)
+ .Case("bycopy", true)
+ .Case("byref", true)
+ .Default(false))
+ Tokens[I].int_data[0] = CXToken_Keyword;
+ continue;
+ }
+
+ if (Cursors[I].kind == CXCursor_CXXFinalAttr ||
+ Cursors[I].kind == CXCursor_CXXOverrideAttr) {
+ Tokens[I].int_data[0] = CXToken_Keyword;
+ continue;
+ }
+ }
+ }
+}
+
+extern "C" {
+
+void clang_annotateTokens(CXTranslationUnit TU,
+ CXToken *Tokens, unsigned NumTokens,
+ CXCursor *Cursors) {
+
+ if (NumTokens == 0 || !Tokens || !Cursors)
+ return;
+
+ // Any token we don't specifically annotate will have a NULL cursor.
+ CXCursor C = clang_getNullCursor();
+ for (unsigned I = 0; I != NumTokens; ++I)
+ Cursors[I] = C;
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
+ if (!CXXUnit)
+ return;
+
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ clang_annotateTokens_Data data = { TU, CXXUnit, Tokens, NumTokens, Cursors };
+ llvm::CrashRecoveryContext CRC;
+ if (!RunSafely(CRC, clang_annotateTokensImpl, &data,
+ GetSafetyThreadStackSize() * 2)) {
+ fprintf(stderr, "libclang: crash detected while annotating tokens\n");
+ }
+}
+
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// Operations for querying linkage of a cursor.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
+ if (!clang_isDeclaration(cursor.kind))
+ return CXLinkage_Invalid;
+
+ Decl *D = cxcursor::getCursorDecl(cursor);
+ if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
+ switch (ND->getLinkage()) {
+ case NoLinkage: return CXLinkage_NoLinkage;
+ case InternalLinkage: return CXLinkage_Internal;
+ case UniqueExternalLinkage: return CXLinkage_UniqueExternal;
+ case ExternalLinkage: return CXLinkage_External;
+ };
+
+ return CXLinkage_Invalid;
+}
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// Operations for querying language of a cursor.
+//===----------------------------------------------------------------------===//
+
+static CXLanguageKind getDeclLanguage(const Decl *D) {
+ if (!D)
+ return CXLanguage_C;
+
+ switch (D->getKind()) {
+ default:
+ break;
+ case Decl::ImplicitParam:
+ case Decl::ObjCAtDefsField:
+ case Decl::ObjCCategory:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCCompatibleAlias:
+ case Decl::ObjCImplementation:
+ case Decl::ObjCInterface:
+ case Decl::ObjCIvar:
+ case Decl::ObjCMethod:
+ case Decl::ObjCProperty:
+ case Decl::ObjCPropertyImpl:
+ case Decl::ObjCProtocol:
+ return CXLanguage_ObjC;
+ case Decl::CXXConstructor:
+ case Decl::CXXConversion:
+ case Decl::CXXDestructor:
+ case Decl::CXXMethod:
+ case Decl::CXXRecord:
+ case Decl::ClassTemplate:
+ case Decl::ClassTemplatePartialSpecialization:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::Friend:
+ case Decl::FriendTemplate:
+ case Decl::FunctionTemplate:
+ case Decl::LinkageSpec:
+ case Decl::Namespace:
+ case Decl::NamespaceAlias:
+ case Decl::NonTypeTemplateParm:
+ case Decl::StaticAssert:
+ case Decl::TemplateTemplateParm:
+ case Decl::TemplateTypeParm:
+ case Decl::UnresolvedUsingTypename:
+ case Decl::UnresolvedUsingValue:
+ case Decl::Using:
+ case Decl::UsingDirective:
+ case Decl::UsingShadow:
+ return CXLanguage_CPlusPlus;
+ }
+
+ return CXLanguage_C;
+}
+
+extern "C" {
+
+enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
+ if (clang_isDeclaration(cursor.kind))
+ if (Decl *D = cxcursor::getCursorDecl(cursor)) {
+ if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted())
+ return CXAvailability_Available;
+
+ switch (D->getAvailability()) {
+ case AR_Available:
+ case AR_NotYetIntroduced:
+ return CXAvailability_Available;
+
+ case AR_Deprecated:
+ return CXAvailability_Deprecated;
+
+ case AR_Unavailable:
+ return CXAvailability_NotAvailable;
+ }
+ }
+
+ return CXAvailability_Available;
+}
+
+static CXVersion convertVersion(VersionTuple In) {
+ CXVersion Out = { -1, -1, -1 };
+ if (In.empty())
+ return Out;
+
+ Out.Major = In.getMajor();
+
+ if (llvm::Optional<unsigned> Minor = In.getMinor())
+ Out.Minor = *Minor;
+ else
+ return Out;
+
+ if (llvm::Optional<unsigned> Subminor = In.getSubminor())
+ Out.Subminor = *Subminor;
+
+ return Out;
+}
+
+int clang_getCursorPlatformAvailability(CXCursor cursor,
+ int *always_deprecated,
+ CXString *deprecated_message,
+ int *always_unavailable,
+ CXString *unavailable_message,
+ CXPlatformAvailability *availability,
+ int availability_size) {
+ if (always_deprecated)
+ *always_deprecated = 0;
+ if (deprecated_message)
+ *deprecated_message = cxstring::createCXString("", /*DupString=*/false);
+ if (always_unavailable)
+ *always_unavailable = 0;
+ if (unavailable_message)
+ *unavailable_message = cxstring::createCXString("", /*DupString=*/false);
+
+ if (!clang_isDeclaration(cursor.kind))
+ return 0;
+
+ Decl *D = cxcursor::getCursorDecl(cursor);
+ if (!D)
+ return 0;
+
+ int N = 0;
+ for (Decl::attr_iterator A = D->attr_begin(), AEnd = D->attr_end(); A != AEnd;
+ ++A) {
+ if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(*A)) {
+ if (always_deprecated)
+ *always_deprecated = 1;
+ if (deprecated_message)
+ *deprecated_message = cxstring::createCXString(Deprecated->getMessage());
+ continue;
+ }
+
+ if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(*A)) {
+ if (always_unavailable)
+ *always_unavailable = 1;
+ if (unavailable_message) {
+ *unavailable_message
+ = cxstring::createCXString(Unavailable->getMessage());
+ }
+ continue;
+ }
+
+ if (AvailabilityAttr *Avail = dyn_cast<AvailabilityAttr>(*A)) {
+ if (N < availability_size) {
+ availability[N].Platform
+ = cxstring::createCXString(Avail->getPlatform()->getName());
+ availability[N].Introduced = convertVersion(Avail->getIntroduced());
+ availability[N].Deprecated = convertVersion(Avail->getDeprecated());
+ availability[N].Obsoleted = convertVersion(Avail->getObsoleted());
+ availability[N].Unavailable = Avail->getUnavailable();
+ availability[N].Message = cxstring::createCXString(Avail->getMessage());
+ }
+ ++N;
+ }
+ }
+
+ return N;
+}
+
+void clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability) {
+ clang_disposeString(availability->Platform);
+ clang_disposeString(availability->Message);
+}
+
+CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
+ if (clang_isDeclaration(cursor.kind))
+ return getDeclLanguage(cxcursor::getCursorDecl(cursor));
+
+ return CXLanguage_Invalid;
+}
+
+ /// \brief If the given cursor is the "templated" declaration
+ /// descibing a class or function template, return the class or
+ /// function template.
+static Decl *maybeGetTemplateCursor(Decl *D) {
+ if (!D)
+ return 0;
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (FunctionTemplateDecl *FunTmpl = FD->getDescribedFunctionTemplate())
+ return FunTmpl;
+
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
+ if (ClassTemplateDecl *ClassTmpl = RD->getDescribedClassTemplate())
+ return ClassTmpl;
+
+ return D;
+}
+
+CXCursor clang_getCursorSemanticParent(CXCursor cursor) {
+ if (clang_isDeclaration(cursor.kind)) {
+ if (Decl *D = getCursorDecl(cursor)) {
+ DeclContext *DC = D->getDeclContext();
+ if (!DC)
+ return clang_getNullCursor();
+
+ return MakeCXCursor(maybeGetTemplateCursor(cast<Decl>(DC)),
+ getCursorTU(cursor));
+ }
+ }
+
+ if (clang_isStatement(cursor.kind) || clang_isExpression(cursor.kind)) {
+ if (Decl *D = getCursorDecl(cursor))
+ return MakeCXCursor(D, getCursorTU(cursor));
+ }
+
+ return clang_getNullCursor();
+}
+
+CXCursor clang_getCursorLexicalParent(CXCursor cursor) {
+ if (clang_isDeclaration(cursor.kind)) {
+ if (Decl *D = getCursorDecl(cursor)) {
+ DeclContext *DC = D->getLexicalDeclContext();
+ if (!DC)
+ return clang_getNullCursor();
+
+ return MakeCXCursor(maybeGetTemplateCursor(cast<Decl>(DC)),
+ getCursorTU(cursor));
+ }
+ }
+
+ // FIXME: Note that we can't easily compute the lexical context of a
+ // statement or expression, so we return nothing.
+ return clang_getNullCursor();
+}
+
+CXFile clang_getIncludedFile(CXCursor cursor) {
+ if (cursor.kind != CXCursor_InclusionDirective)
+ return 0;
+
+ InclusionDirective *ID = getCursorInclusionDirective(cursor);
+ return (void *)ID->getFile();
+}
+
+CXSourceRange clang_Cursor_getCommentRange(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return clang_getNullRange();
+
+ const Decl *D = getCursorDecl(C);
+ ASTContext &Context = getCursorContext(C);
+ const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
+ if (!RC)
+ return clang_getNullRange();
+
+ return cxloc::translateSourceRange(Context, RC->getSourceRange());
+}
+
+CXString clang_Cursor_getRawCommentText(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return createCXString((const char *) NULL);
+
+ const Decl *D = getCursorDecl(C);
+ ASTContext &Context = getCursorContext(C);
+ const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
+ StringRef RawText = RC ? RC->getRawText(Context.getSourceManager()) :
+ StringRef();
+
+ // Don't duplicate the string because RawText points directly into source
+ // code.
+ return createCXString(RawText, false);
+}
+
+CXString clang_Cursor_getBriefCommentText(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return createCXString((const char *) NULL);
+
+ const Decl *D = getCursorDecl(C);
+ const ASTContext &Context = getCursorContext(C);
+ const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
+
+ if (RC) {
+ StringRef BriefText = RC->getBriefText(Context);
+
+ // Don't duplicate the string because RawComment ensures that this memory
+ // will not go away.
+ return createCXString(BriefText, false);
+ }
+
+ return createCXString((const char *) NULL);
+}
+
+CXComment clang_Cursor_getParsedComment(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return cxcomment::createCXComment(NULL, NULL);
+
+ const Decl *D = getCursorDecl(C);
+ const ASTContext &Context = getCursorContext(C);
+ const comments::FullComment *FC = Context.getCommentForDecl(D, /*PP=*/ NULL);
+
+ return cxcomment::createCXComment(FC, getCursorTU(C));
+}
+
+CXModule clang_Cursor_getModule(CXCursor C) {
+ if (C.kind == CXCursor_ModuleImportDecl) {
+ if (ImportDecl *ImportD = dyn_cast_or_null<ImportDecl>(getCursorDecl(C)))
+ return ImportD->getImportedModule();
+ }
+
+ return 0;
+}
+
+CXModule clang_Module_getParent(CXModule CXMod) {
+ if (!CXMod)
+ return 0;
+ Module *Mod = static_cast<Module*>(CXMod);
+ return Mod->Parent;
+}
+
+CXString clang_Module_getName(CXModule CXMod) {
+ if (!CXMod)
+ return createCXString("");
+ Module *Mod = static_cast<Module*>(CXMod);
+ return createCXString(Mod->Name);
+}
+
+CXString clang_Module_getFullName(CXModule CXMod) {
+ if (!CXMod)
+ return createCXString("");
+ Module *Mod = static_cast<Module*>(CXMod);
+ return createCXString(Mod->getFullModuleName());
+}
+
+unsigned clang_Module_getNumTopLevelHeaders(CXModule CXMod) {
+ if (!CXMod)
+ return 0;
+ Module *Mod = static_cast<Module*>(CXMod);
+ return Mod->TopHeaders.size();
+}
+
+CXFile clang_Module_getTopLevelHeader(CXModule CXMod, unsigned Index) {
+ if (!CXMod)
+ return 0;
+ Module *Mod = static_cast<Module*>(CXMod);
+
+ if (Index < Mod->TopHeaders.size())
+ return const_cast<FileEntry *>(Mod->TopHeaders[Index]);
+
+ return 0;
+}
+
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// C++ AST instrospection.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+unsigned clang_CXXMethod_isStatic(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ CXXMethodDecl *Method = 0;
+ Decl *D = cxcursor::getCursorDecl(C);
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
+ Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+ else
+ Method = dyn_cast_or_null<CXXMethodDecl>(D);
+ return (Method && Method->isStatic()) ? 1 : 0;
+}
+
+unsigned clang_CXXMethod_isVirtual(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ CXXMethodDecl *Method = 0;
+ Decl *D = cxcursor::getCursorDecl(C);
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
+ Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+ else
+ Method = dyn_cast_or_null<CXXMethodDecl>(D);
+ return (Method && Method->isVirtual()) ? 1 : 0;
+}
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// Attribute introspection.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+CXType clang_getIBOutletCollectionType(CXCursor C) {
+ if (C.kind != CXCursor_IBOutletCollectionAttr)
+ return cxtype::MakeCXType(QualType(), cxcursor::getCursorTU(C));
+
+ IBOutletCollectionAttr *A =
+ cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(C));
+
+ return cxtype::MakeCXType(A->getInterface(), cxcursor::getCursorTU(C));
+}
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// Inspecting memory usage.
+//===----------------------------------------------------------------------===//
+
+typedef std::vector<CXTUResourceUsageEntry> MemUsageEntries;
+
+static inline void createCXTUResourceUsageEntry(MemUsageEntries &entries,
+ enum CXTUResourceUsageKind k,
+ unsigned long amount) {
+ CXTUResourceUsageEntry entry = { k, amount };
+ entries.push_back(entry);
+}
+
+extern "C" {
+
+const char *clang_getTUResourceUsageName(CXTUResourceUsageKind kind) {
+ const char *str = "";
+ switch (kind) {
+ case CXTUResourceUsage_AST:
+ str = "ASTContext: expressions, declarations, and types";
+ break;
+ case CXTUResourceUsage_Identifiers:
+ str = "ASTContext: identifiers";
+ break;
+ case CXTUResourceUsage_Selectors:
+ str = "ASTContext: selectors";
+ break;
+ case CXTUResourceUsage_GlobalCompletionResults:
+ str = "Code completion: cached global results";
+ break;
+ case CXTUResourceUsage_SourceManagerContentCache:
+ str = "SourceManager: content cache allocator";
+ break;
+ case CXTUResourceUsage_AST_SideTables:
+ str = "ASTContext: side tables";
+ break;
+ case CXTUResourceUsage_SourceManager_Membuffer_Malloc:
+ str = "SourceManager: malloc'ed memory buffers";
+ break;
+ case CXTUResourceUsage_SourceManager_Membuffer_MMap:
+ str = "SourceManager: mmap'ed memory buffers";
+ break;
+ case CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc:
+ str = "ExternalASTSource: malloc'ed memory buffers";
+ break;
+ case CXTUResourceUsage_ExternalASTSource_Membuffer_MMap:
+ str = "ExternalASTSource: mmap'ed memory buffers";
+ break;
+ case CXTUResourceUsage_Preprocessor:
+ str = "Preprocessor: malloc'ed memory";
+ break;
+ case CXTUResourceUsage_PreprocessingRecord:
+ str = "Preprocessor: PreprocessingRecord";
+ break;
+ case CXTUResourceUsage_SourceManager_DataStructures:
+ str = "SourceManager: data structures and tables";
+ break;
+ case CXTUResourceUsage_Preprocessor_HeaderSearch:
+ str = "Preprocessor: header search tables";
+ break;
+ }
+ return str;
+}
+
+CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU) {
+ if (!TU) {
+ CXTUResourceUsage usage = { (void*) 0, 0, 0 };
+ return usage;
+ }
+
+ ASTUnit *astUnit = static_cast<ASTUnit*>(TU->TUData);
+ OwningPtr<MemUsageEntries> entries(new MemUsageEntries());
+ ASTContext &astContext = astUnit->getASTContext();
+
+ // How much memory is used by AST nodes and types?
+ createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_AST,
+ (unsigned long) astContext.getASTAllocatedMemory());
+
+ // How much memory is used by identifiers?
+ createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_Identifiers,
+ (unsigned long) astContext.Idents.getAllocator().getTotalMemory());
+
+ // How much memory is used for selectors?
+ createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_Selectors,
+ (unsigned long) astContext.Selectors.getTotalMemory());
+
+ // How much memory is used by ASTContext's side tables?
+ createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_AST_SideTables,
+ (unsigned long) astContext.getSideTableAllocatedMemory());
+
+ // How much memory is used for caching global code completion results?
+ unsigned long completionBytes = 0;
+ if (GlobalCodeCompletionAllocator *completionAllocator =
+ astUnit->getCachedCompletionAllocator().getPtr()) {
+ completionBytes = completionAllocator->getTotalMemory();
+ }
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_GlobalCompletionResults,
+ completionBytes);
+
+ // How much memory is being used by SourceManager's content cache?
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_SourceManagerContentCache,
+ (unsigned long) astContext.getSourceManager().getContentCacheSize());
+
+ // How much memory is being used by the MemoryBuffer's in SourceManager?
+ const SourceManager::MemoryBufferSizes &srcBufs =
+ astUnit->getSourceManager().getMemoryBufferSizes();
+
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_SourceManager_Membuffer_Malloc,
+ (unsigned long) srcBufs.malloc_bytes);
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_SourceManager_Membuffer_MMap,
+ (unsigned long) srcBufs.mmap_bytes);
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_SourceManager_DataStructures,
+ (unsigned long) astContext.getSourceManager()
+ .getDataStructureSizes());
+
+ // How much memory is being used by the ExternalASTSource?
+ if (ExternalASTSource *esrc = astContext.getExternalSource()) {
+ const ExternalASTSource::MemoryBufferSizes &sizes =
+ esrc->getMemoryBufferSizes();
+
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc,
+ (unsigned long) sizes.malloc_bytes);
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_ExternalASTSource_Membuffer_MMap,
+ (unsigned long) sizes.mmap_bytes);
+ }
+
+ // How much memory is being used by the Preprocessor?
+ Preprocessor &pp = astUnit->getPreprocessor();
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_Preprocessor,
+ pp.getTotalMemory());
+
+ if (PreprocessingRecord *pRec = pp.getPreprocessingRecord()) {
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_PreprocessingRecord,
+ pRec->getTotalMemory());
+ }
+
+ createCXTUResourceUsageEntry(*entries,
+ CXTUResourceUsage_Preprocessor_HeaderSearch,
+ pp.getHeaderSearchInfo().getTotalMemory());
+
+ CXTUResourceUsage usage = { (void*) entries.get(),
+ (unsigned) entries->size(),
+ entries->size() ? &(*entries)[0] : 0 };
+ entries.take();
+ return usage;
+}
+
+void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage) {
+ if (usage.data)
+ delete (MemUsageEntries*) usage.data;
+}
+
+} // end extern "C"
+
+void clang::PrintLibclangResourceUsage(CXTranslationUnit TU) {
+ CXTUResourceUsage Usage = clang_getCXTUResourceUsage(TU);
+ for (unsigned I = 0; I != Usage.numEntries; ++I)
+ fprintf(stderr, " %s: %lu\n",
+ clang_getTUResourceUsageName(Usage.entries[I].kind),
+ Usage.entries[I].amount);
+
+ clang_disposeCXTUResourceUsage(Usage);
+}
+
+//===----------------------------------------------------------------------===//
+// Misc. utility functions.
+//===----------------------------------------------------------------------===//
+
+/// Default to using an 8 MB stack size on "safety" threads.
+static unsigned SafetyStackThreadSize = 8 << 20;
+
+namespace clang {
+
+bool RunSafely(llvm::CrashRecoveryContext &CRC,
+ void (*Fn)(void*), void *UserData,
+ unsigned Size) {
+ if (!Size)
+ Size = GetSafetyThreadStackSize();
+ if (Size)
+ return CRC.RunSafelyOnThread(Fn, UserData, Size);
+ return CRC.RunSafely(Fn, UserData);
+}
+
+unsigned GetSafetyThreadStackSize() {
+ return SafetyStackThreadSize;
+}
+
+void SetSafetyThreadStackSize(unsigned Value) {
+ SafetyStackThreadSize = Value;
+}
+
+}
+
+void clang::setThreadBackgroundPriority() {
+ if (getenv("LIBCLANG_BGPRIO_DISABLE"))
+ return;
+
+ // FIXME: Move to llvm/Support and make it cross-platform.
+#ifdef __APPLE__
+ setpriority(PRIO_DARWIN_THREAD, 0, PRIO_DARWIN_BG);
+#endif
+}
+
+void cxindex::printDiagsToStderr(ASTUnit *Unit) {
+ if (!Unit)
+ return;
+
+ for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),
+ DEnd = Unit->stored_diag_end();
+ D != DEnd; ++D) {
+ CXStoredDiagnostic Diag(*D, Unit->getASTContext().getLangOpts());
+ CXString Msg = clang_formatDiagnostic(&Diag,
+ clang_defaultDiagnosticDisplayOptions());
+ fprintf(stderr, "%s\n", clang_getCString(Msg));
+ clang_disposeString(Msg);
+ }
+#ifdef LLVM_ON_WIN32
+ // On Windows, force a flush, since there may be multiple copies of
+ // stderr and stdout in the file system, all with different buffers
+ // but writing to the same device.
+ fflush(stderr);
+#endif
+}
+
+extern "C" {
+
+CXString clang_getClangVersion() {
+ return createCXString(getClangFullVersion());
+}
+
+} // end: extern "C"
+
-//===- CIndexUSR.cpp - Clang-C Source Indexing Library --------------------===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This file implements the generation and use of USRs from CXEntities.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "CIndexer.h"\r
-#include "CXCursor.h"\r
-#include "CXString.h"\r
-#include "clang/AST/DeclTemplate.h"\r
-#include "clang/AST/DeclVisitor.h"\r
-#include "clang/Frontend/ASTUnit.h"\r
-#include "clang/Lex/PreprocessingRecord.h"\r
-#include "llvm/ADT/SmallString.h"\r
-#include "llvm/Support/raw_ostream.h"\r
-\r
-using namespace clang;\r
-using namespace clang::cxstring;\r
-\r
-//===----------------------------------------------------------------------===//\r
-// USR generation.\r
-//===----------------------------------------------------------------------===//\r
-\r
-namespace {\r
-class USRGenerator : public DeclVisitor<USRGenerator> {\r
- OwningPtr<SmallString<128> > OwnedBuf;\r
- SmallVectorImpl<char> &Buf;\r
- llvm::raw_svector_ostream Out;\r
- bool IgnoreResults;\r
- ASTContext *Context;\r
- bool generatedLoc;\r
- \r
- llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;\r
- \r
-public:\r
- explicit USRGenerator(ASTContext *Ctx = 0, SmallVectorImpl<char> *extBuf = 0)\r
- : OwnedBuf(extBuf ? 0 : new SmallString<128>()),\r
- Buf(extBuf ? *extBuf : *OwnedBuf.get()),\r
- Out(Buf),\r
- IgnoreResults(false),\r
- Context(Ctx),\r
- generatedLoc(false)\r
- {\r
- // Add the USR space prefix.\r
- Out << "c:";\r
- }\r
-\r
- StringRef str() {\r
- return Out.str();\r
- }\r
-\r
- USRGenerator* operator->() { return this; }\r
-\r
- template <typename T>\r
- llvm::raw_svector_ostream &operator<<(const T &x) {\r
- Out << x;\r
- return Out;\r
- }\r
-\r
- bool ignoreResults() const { return IgnoreResults; }\r
-\r
- // Visitation methods from generating USRs from AST elements.\r
- void VisitDeclContext(DeclContext *D);\r
- void VisitFieldDecl(FieldDecl *D);\r
- void VisitFunctionDecl(FunctionDecl *D);\r
- void VisitNamedDecl(NamedDecl *D);\r
- void VisitNamespaceDecl(NamespaceDecl *D);\r
- void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);\r
- void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);\r
- void VisitClassTemplateDecl(ClassTemplateDecl *D);\r
- void VisitObjCContainerDecl(ObjCContainerDecl *CD);\r
- void VisitObjCMethodDecl(ObjCMethodDecl *MD);\r
- void VisitObjCPropertyDecl(ObjCPropertyDecl *D);\r
- void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);\r
- void VisitTagDecl(TagDecl *D);\r
- void VisitTypedefDecl(TypedefDecl *D);\r
- void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);\r
- void VisitVarDecl(VarDecl *D);\r
- void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);\r
- void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);\r
- void VisitLinkageSpecDecl(LinkageSpecDecl *D) {\r
- IgnoreResults = true;\r
- }\r
- void VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {\r
- IgnoreResults = true;\r
- }\r
- void VisitUsingDecl(UsingDecl *D) { \r
- IgnoreResults = true;\r
- }\r
- void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { \r
- IgnoreResults = true;\r
- }\r
- void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { \r
- IgnoreResults = true;\r
- }\r
- \r
- /// Generate the string component containing the location of the\r
- /// declaration.\r
- bool GenLoc(const Decl *D);\r
-\r
- /// String generation methods used both by the visitation methods\r
- /// and from other clients that want to directly generate USRs. These\r
- /// methods do not construct complete USRs (which incorporate the parents\r
- /// of an AST element), but only the fragments concerning the AST element\r
- /// itself.\r
-\r
- /// Generate a USR for an Objective-C class.\r
- void GenObjCClass(StringRef cls);\r
- /// Generate a USR for an Objective-C class category.\r
- void GenObjCCategory(StringRef cls, StringRef cat);\r
- /// Generate a USR fragment for an Objective-C instance variable. The\r
- /// complete USR can be created by concatenating the USR for the\r
- /// encompassing class with this USR fragment.\r
- void GenObjCIvar(StringRef ivar);\r
- /// Generate a USR fragment for an Objective-C method.\r
- void GenObjCMethod(StringRef sel, bool isInstanceMethod);\r
- /// Generate a USR fragment for an Objective-C property.\r
- void GenObjCProperty(StringRef prop);\r
- /// Generate a USR for an Objective-C protocol.\r
- void GenObjCProtocol(StringRef prot);\r
-\r
- void VisitType(QualType T);\r
- void VisitTemplateParameterList(const TemplateParameterList *Params);\r
- void VisitTemplateName(TemplateName Name);\r
- void VisitTemplateArgument(const TemplateArgument &Arg);\r
- \r
- /// Emit a Decl's name using NamedDecl::printName() and return true if\r
- /// the decl had no name.\r
- bool EmitDeclName(const NamedDecl *D);\r
-};\r
-\r
-} // end anonymous namespace\r
-\r
-//===----------------------------------------------------------------------===//\r
-// Generating USRs from ASTS.\r
-//===----------------------------------------------------------------------===//\r
-\r
-bool USRGenerator::EmitDeclName(const NamedDecl *D) {\r
- Out.flush();\r
- const unsigned startSize = Buf.size();\r
- D->printName(Out);\r
- Out.flush();\r
- const unsigned endSize = Buf.size();\r
- return startSize == endSize;\r
-}\r
-\r
-static inline bool ShouldGenerateLocation(const NamedDecl *D) {\r
- return D->getLinkage() != ExternalLinkage;\r
-}\r
-\r
-void USRGenerator::VisitDeclContext(DeclContext *DC) {\r
- if (NamedDecl *D = dyn_cast<NamedDecl>(DC))\r
- Visit(D);\r
-}\r
-\r
-void USRGenerator::VisitFieldDecl(FieldDecl *D) {\r
- // The USR for an ivar declared in a class extension is based on the\r
- // ObjCInterfaceDecl, not the ObjCCategoryDecl.\r
- if (ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))\r
- Visit(ID);\r
- else\r
- VisitDeclContext(D->getDeclContext());\r
- Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");\r
- if (EmitDeclName(D)) {\r
- // Bit fields can be anonymous.\r
- IgnoreResults = true;\r
- return;\r
- }\r
-}\r
-\r
-void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {\r
- if (ShouldGenerateLocation(D) && GenLoc(D))\r
- return;\r
-\r
- VisitDeclContext(D->getDeclContext());\r
- if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {\r
- Out << "@FT@";\r
- VisitTemplateParameterList(FunTmpl->getTemplateParameters());\r
- } else\r
- Out << "@F@";\r
- D->printName(Out);\r
-\r
- ASTContext &Ctx = *Context;\r
- if (!Ctx.getLangOpts().CPlusPlus || D->isExternC())\r
- return;\r
-\r
- if (const TemplateArgumentList *\r
- SpecArgs = D->getTemplateSpecializationArgs()) {\r
- Out << '<';\r
- for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) {\r
- Out << '#';\r
- VisitTemplateArgument(SpecArgs->get(I));\r
- }\r
- Out << '>';\r
- }\r
-\r
- // Mangle in type information for the arguments.\r
- for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end();\r
- I != E; ++I) {\r
- Out << '#';\r
- if (ParmVarDecl *PD = *I)\r
- VisitType(PD->getType());\r
- }\r
- if (D->isVariadic())\r
- Out << '.';\r
- Out << '#';\r
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {\r
- if (MD->isStatic())\r
- Out << 'S';\r
- if (unsigned quals = MD->getTypeQualifiers())\r
- Out << (char)('0' + quals);\r
- }\r
-}\r
-\r
-void USRGenerator::VisitNamedDecl(NamedDecl *D) {\r
- VisitDeclContext(D->getDeclContext());\r
- Out << "@";\r
-\r
- if (EmitDeclName(D)) {\r
- // The string can be empty if the declaration has no name; e.g., it is\r
- // the ParmDecl with no name for declaration of a function pointer type,\r
- // e.g.: void (*f)(void *);\r
- // In this case, don't generate a USR.\r
- IgnoreResults = true;\r
- }\r
-}\r
-\r
-void USRGenerator::VisitVarDecl(VarDecl *D) {\r
- // VarDecls can be declared 'extern' within a function or method body,\r
- // but their enclosing DeclContext is the function, not the TU. We need\r
- // to check the storage class to correctly generate the USR.\r
- if (ShouldGenerateLocation(D) && GenLoc(D))\r
- return;\r
-\r
- VisitDeclContext(D->getDeclContext());\r
-\r
- // Variables always have simple names.\r
- StringRef s = D->getName();\r
-\r
- // The string can be empty if the declaration has no name; e.g., it is\r
- // the ParmDecl with no name for declaration of a function pointer type, e.g.:\r
- // void (*f)(void *);\r
- // In this case, don't generate a USR.\r
- if (s.empty())\r
- IgnoreResults = true;\r
- else\r
- Out << '@' << s;\r
-}\r
-\r
-void USRGenerator::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {\r
- GenLoc(D);\r
- return;\r
-}\r
-\r
-void USRGenerator::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {\r
- GenLoc(D);\r
- return;\r
-}\r
-\r
-void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {\r
- if (D->isAnonymousNamespace()) {\r
- Out << "@aN";\r
- return;\r
- }\r
-\r
- VisitDeclContext(D->getDeclContext());\r
- if (!IgnoreResults)\r
- Out << "@N@" << D->getName();\r
-}\r
-\r
-void USRGenerator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {\r
- VisitFunctionDecl(D->getTemplatedDecl());\r
-}\r
-\r
-void USRGenerator::VisitClassTemplateDecl(ClassTemplateDecl *D) {\r
- VisitTagDecl(D->getTemplatedDecl());\r
-}\r
-\r
-void USRGenerator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {\r
- VisitDeclContext(D->getDeclContext());\r
- if (!IgnoreResults)\r
- Out << "@NA@" << D->getName(); \r
-}\r
-\r
-void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {\r
- DeclContext *container = D->getDeclContext();\r
- if (ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {\r
- Visit(pd);\r
- }\r
- else {\r
- // The USR for a method declared in a class extension or category is based on\r
- // the ObjCInterfaceDecl, not the ObjCCategoryDecl.\r
- ObjCInterfaceDecl *ID = D->getClassInterface();\r
- if (!ID) {\r
- IgnoreResults = true;\r
- return;\r
- }\r
- Visit(ID);\r
- }\r
- // Ideally we would use 'GenObjCMethod', but this is such a hot path\r
- // for Objective-C code that we don't want to use\r
- // DeclarationName::getAsString().\r
- Out << (D->isInstanceMethod() ? "(im)" : "(cm)");\r
- DeclarationName N(D->getSelector());\r
- N.printName(Out);\r
-}\r
-\r
-void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {\r
- switch (D->getKind()) {\r
- default:\r
- llvm_unreachable("Invalid ObjC container.");\r
- case Decl::ObjCInterface:\r
- case Decl::ObjCImplementation:\r
- GenObjCClass(D->getName());\r
- break;\r
- case Decl::ObjCCategory: {\r
- ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);\r
- ObjCInterfaceDecl *ID = CD->getClassInterface();\r
- if (!ID) {\r
- // Handle invalid code where the @interface might not\r
- // have been specified.\r
- // FIXME: We should be able to generate this USR even if the\r
- // @interface isn't available.\r
- IgnoreResults = true;\r
- return;\r
- }\r
- // Specially handle class extensions, which are anonymous categories.\r
- // We want to mangle in the location to uniquely distinguish them.\r
- if (CD->IsClassExtension()) {\r
- Out << "objc(ext)" << ID->getName() << '@';\r
- GenLoc(CD);\r
- }\r
- else\r
- GenObjCCategory(ID->getName(), CD->getName());\r
-\r
- break;\r
- }\r
- case Decl::ObjCCategoryImpl: {\r
- ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);\r
- ObjCInterfaceDecl *ID = CD->getClassInterface();\r
- if (!ID) {\r
- // Handle invalid code where the @interface might not\r
- // have been specified.\r
- // FIXME: We should be able to generate this USR even if the\r
- // @interface isn't available.\r
- IgnoreResults = true;\r
- return;\r
- }\r
- GenObjCCategory(ID->getName(), CD->getName());\r
- break;\r
- }\r
- case Decl::ObjCProtocol:\r
- GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName());\r
- break;\r
- }\r
-}\r
-\r
-void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {\r
- // The USR for a property declared in a class extension or category is based\r
- // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.\r
- if (ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))\r
- Visit(ID);\r
- else\r
- Visit(cast<Decl>(D->getDeclContext()));\r
- GenObjCProperty(D->getName());\r
-}\r
-\r
-void USRGenerator::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {\r
- if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {\r
- VisitObjCPropertyDecl(PD);\r
- return;\r
- }\r
-\r
- IgnoreResults = true;\r
-}\r
-\r
-void USRGenerator::VisitTagDecl(TagDecl *D) {\r
- // Add the location of the tag decl to handle resolution across\r
- // translation units.\r
- if (ShouldGenerateLocation(D) && GenLoc(D))\r
- return;\r
-\r
- D = D->getCanonicalDecl();\r
- VisitDeclContext(D->getDeclContext());\r
-\r
- bool AlreadyStarted = false;\r
- if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {\r
- if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {\r
- AlreadyStarted = true;\r
- \r
- switch (D->getTagKind()) {\r
- case TTK_Interface:\r
- case TTK_Struct: Out << "@ST"; break;\r
- case TTK_Class: Out << "@CT"; break;\r
- case TTK_Union: Out << "@UT"; break;\r
- case TTK_Enum: llvm_unreachable("enum template");\r
- }\r
- VisitTemplateParameterList(ClassTmpl->getTemplateParameters());\r
- } else if (ClassTemplatePartialSpecializationDecl *PartialSpec\r
- = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {\r
- AlreadyStarted = true;\r
- \r
- switch (D->getTagKind()) {\r
- case TTK_Interface:\r
- case TTK_Struct: Out << "@SP"; break;\r
- case TTK_Class: Out << "@CP"; break;\r
- case TTK_Union: Out << "@UP"; break;\r
- case TTK_Enum: llvm_unreachable("enum partial specialization");\r
- } \r
- VisitTemplateParameterList(PartialSpec->getTemplateParameters());\r
- }\r
- }\r
- \r
- if (!AlreadyStarted) {\r
- switch (D->getTagKind()) {\r
- case TTK_Interface:\r
- case TTK_Struct: Out << "@S"; break;\r
- case TTK_Class: Out << "@C"; break;\r
- case TTK_Union: Out << "@U"; break;\r
- case TTK_Enum: Out << "@E"; break;\r
- }\r
- }\r
- \r
- Out << '@';\r
- Out.flush();\r
- assert(Buf.size() > 0);\r
- const unsigned off = Buf.size() - 1;\r
-\r
- if (EmitDeclName(D)) {\r
- if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {\r
- Buf[off] = 'A';\r
- Out << '@' << *TD;\r
- }\r
- else\r
- Buf[off] = 'a';\r
- }\r
- \r
- // For a class template specialization, mangle the template arguments.\r
- if (ClassTemplateSpecializationDecl *Spec\r
- = dyn_cast<ClassTemplateSpecializationDecl>(D)) {\r
- const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs();\r
- Out << '>';\r
- for (unsigned I = 0, N = Args.size(); I != N; ++I) {\r
- Out << '#';\r
- VisitTemplateArgument(Args.get(I));\r
- }\r
- }\r
-}\r
-\r
-void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {\r
- if (ShouldGenerateLocation(D) && GenLoc(D))\r
- return;\r
- DeclContext *DC = D->getDeclContext();\r
- if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))\r
- Visit(DCN);\r
- Out << "@T@";\r
- Out << D->getName();\r
-}\r
-\r
-void USRGenerator::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {\r
- GenLoc(D);\r
- return;\r
-}\r
-\r
-bool USRGenerator::GenLoc(const Decl *D) {\r
- if (generatedLoc)\r
- return IgnoreResults;\r
- generatedLoc = true;\r
- \r
- // Guard against null declarations in invalid code.\r
- if (!D) {\r
- IgnoreResults = true;\r
- return true;\r
- }\r
-\r
- // Use the location of canonical decl.\r
- D = D->getCanonicalDecl();\r
-\r
- const SourceManager &SM = Context->getSourceManager();\r
- SourceLocation L = D->getLocStart();\r
- if (L.isInvalid()) {\r
- IgnoreResults = true;\r
- return true;\r
- }\r
- L = SM.getExpansionLoc(L);\r
- const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(L);\r
- const FileEntry *FE = SM.getFileEntryForID(Decomposed.first);\r
- if (FE) {\r
- Out << llvm::sys::path::filename(FE->getName());\r
- }\r
- else {\r
- // This case really isn't interesting.\r
- IgnoreResults = true;\r
- return true;\r
- }\r
- // Use the offest into the FileID to represent the location. Using\r
- // a line/column can cause us to look back at the original source file,\r
- // which is expensive.\r
- Out << '@' << Decomposed.second;\r
- return IgnoreResults;\r
-}\r
-\r
-void USRGenerator::VisitType(QualType T) {\r
- // This method mangles in USR information for types. It can possibly\r
- // just reuse the naming-mangling logic used by codegen, although the\r
- // requirements for USRs might not be the same.\r
- ASTContext &Ctx = *Context;\r
-\r
- do {\r
- T = Ctx.getCanonicalType(T);\r
- Qualifiers Q = T.getQualifiers();\r
- unsigned qVal = 0;\r
- if (Q.hasConst())\r
- qVal |= 0x1;\r
- if (Q.hasVolatile())\r
- qVal |= 0x2;\r
- if (Q.hasRestrict())\r
- qVal |= 0x4;\r
- if(qVal)\r
- Out << ((char) ('0' + qVal));\r
-\r
- // Mangle in ObjC GC qualifiers?\r
-\r
- if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {\r
- Out << 'P';\r
- T = Expansion->getPattern();\r
- }\r
- \r
- if (const BuiltinType *BT = T->getAs<BuiltinType>()) {\r
- unsigned char c = '\0';\r
- switch (BT->getKind()) {\r
- case BuiltinType::Void:\r
- c = 'v'; break;\r
- case BuiltinType::Bool:\r
- c = 'b'; break;\r
- case BuiltinType::Char_U:\r
- case BuiltinType::UChar:\r
- c = 'c'; break;\r
- case BuiltinType::Char16:\r
- c = 'q'; break;\r
- case BuiltinType::Char32:\r
- c = 'w'; break;\r
- case BuiltinType::UShort:\r
- c = 's'; break;\r
- case BuiltinType::UInt:\r
- c = 'i'; break;\r
- case BuiltinType::ULong:\r
- c = 'l'; break;\r
- case BuiltinType::ULongLong:\r
- c = 'k'; break;\r
- case BuiltinType::UInt128:\r
- c = 'j'; break;\r
- case BuiltinType::Char_S:\r
- case BuiltinType::SChar:\r
- c = 'C'; break;\r
- case BuiltinType::WChar_S:\r
- case BuiltinType::WChar_U:\r
- c = 'W'; break;\r
- case BuiltinType::Short:\r
- c = 'S'; break;\r
- case BuiltinType::Int:\r
- c = 'I'; break;\r
- case BuiltinType::Long:\r
- c = 'L'; break;\r
- case BuiltinType::LongLong:\r
- c = 'K'; break;\r
- case BuiltinType::Int128:\r
- c = 'J'; break;\r
- case BuiltinType::Half:\r
- c = 'h'; break;\r
- case BuiltinType::Float:\r
- c = 'f'; break;\r
- case BuiltinType::Double:\r
- c = 'd'; break;\r
- case BuiltinType::LongDouble:\r
- c = 'D'; break;\r
- case BuiltinType::NullPtr:\r
- c = 'n'; break;\r
-#define BUILTIN_TYPE(Id, SingletonId)\r
-#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:\r
-#include "clang/AST/BuiltinTypes.def"\r
- case BuiltinType::Dependent:\r
- case BuiltinType::OCLImage1d:\r
- case BuiltinType::OCLImage1dArray:\r
- case BuiltinType::OCLImage1dBuffer:\r
- case BuiltinType::OCLImage2d:\r
- case BuiltinType::OCLImage2dArray:\r
- case BuiltinType::OCLImage3d:\r
- IgnoreResults = true;\r
- return;\r
- case BuiltinType::ObjCId:\r
- c = 'o'; break;\r
- case BuiltinType::ObjCClass:\r
- c = 'O'; break;\r
- case BuiltinType::ObjCSel:\r
- c = 'e'; break;\r
- }\r
- Out << c;\r
- return;\r
- }\r
-\r
- // If we have already seen this (non-built-in) type, use a substitution\r
- // encoding.\r
- llvm::DenseMap<const Type *, unsigned>::iterator Substitution\r
- = TypeSubstitutions.find(T.getTypePtr());\r
- if (Substitution != TypeSubstitutions.end()) {\r
- Out << 'S' << Substitution->second << '_';\r
- return;\r
- } else {\r
- // Record this as a substitution.\r
- unsigned Number = TypeSubstitutions.size();\r
- TypeSubstitutions[T.getTypePtr()] = Number;\r
- }\r
- \r
- if (const PointerType *PT = T->getAs<PointerType>()) {\r
- Out << '*';\r
- T = PT->getPointeeType();\r
- continue;\r
- }\r
- if (const ReferenceType *RT = T->getAs<ReferenceType>()) {\r
- Out << '&';\r
- T = RT->getPointeeType();\r
- continue;\r
- }\r
- if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {\r
- Out << 'F';\r
- VisitType(FT->getResultType());\r
- for (FunctionProtoType::arg_type_iterator\r
- I = FT->arg_type_begin(), E = FT->arg_type_end(); I!=E; ++I) {\r
- VisitType(*I);\r
- }\r
- if (FT->isVariadic())\r
- Out << '.';\r
- return;\r
- }\r
- if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {\r
- Out << 'B';\r
- T = BT->getPointeeType();\r
- continue;\r
- }\r
- if (const ComplexType *CT = T->getAs<ComplexType>()) {\r
- Out << '<';\r
- T = CT->getElementType();\r
- continue;\r
- }\r
- if (const TagType *TT = T->getAs<TagType>()) {\r
- Out << '$';\r
- VisitTagDecl(TT->getDecl());\r
- return;\r
- }\r
- if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {\r
- Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();\r
- return;\r
- }\r
- if (const TemplateSpecializationType *Spec\r
- = T->getAs<TemplateSpecializationType>()) {\r
- Out << '>';\r
- VisitTemplateName(Spec->getTemplateName());\r
- Out << Spec->getNumArgs();\r
- for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)\r
- VisitTemplateArgument(Spec->getArg(I));\r
- return;\r
- }\r
- \r
- // Unhandled type.\r
- Out << ' ';\r
- break;\r
- } while (true);\r
-}\r
-\r
-void USRGenerator::VisitTemplateParameterList(\r
- const TemplateParameterList *Params) {\r
- if (!Params)\r
- return;\r
- Out << '>' << Params->size();\r
- for (TemplateParameterList::const_iterator P = Params->begin(),\r
- PEnd = Params->end();\r
- P != PEnd; ++P) {\r
- Out << '#';\r
- if (isa<TemplateTypeParmDecl>(*P)) {\r
- if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())\r
- Out<< 'p';\r
- Out << 'T';\r
- continue;\r
- }\r
- \r
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {\r
- if (NTTP->isParameterPack())\r
- Out << 'p';\r
- Out << 'N';\r
- VisitType(NTTP->getType());\r
- continue;\r
- }\r
- \r
- TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);\r
- if (TTP->isParameterPack())\r
- Out << 'p';\r
- Out << 't';\r
- VisitTemplateParameterList(TTP->getTemplateParameters());\r
- }\r
-}\r
-\r
-void USRGenerator::VisitTemplateName(TemplateName Name) {\r
- if (TemplateDecl *Template = Name.getAsTemplateDecl()) {\r
- if (TemplateTemplateParmDecl *TTP\r
- = dyn_cast<TemplateTemplateParmDecl>(Template)) {\r
- Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();\r
- return;\r
- }\r
- \r
- Visit(Template);\r
- return;\r
- }\r
- \r
- // FIXME: Visit dependent template names.\r
-}\r
-\r
-void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {\r
- switch (Arg.getKind()) {\r
- case TemplateArgument::Null:\r
- break;\r
-\r
- case TemplateArgument::Declaration:\r
- Visit(Arg.getAsDecl());\r
- break;\r
-\r
- case TemplateArgument::NullPtr:\r
- break;\r
-\r
- case TemplateArgument::TemplateExpansion:\r
- Out << 'P'; // pack expansion of...\r
- // Fall through\r
- case TemplateArgument::Template:\r
- VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());\r
- break;\r
- \r
- case TemplateArgument::Expression:\r
- // FIXME: Visit expressions.\r
- break;\r
- \r
- case TemplateArgument::Pack:\r
- Out << 'p' << Arg.pack_size();\r
- for (TemplateArgument::pack_iterator P = Arg.pack_begin(), PEnd = Arg.pack_end();\r
- P != PEnd; ++P)\r
- VisitTemplateArgument(*P);\r
- break;\r
- \r
- case TemplateArgument::Type:\r
- VisitType(Arg.getAsType());\r
- break;\r
- \r
- case TemplateArgument::Integral:\r
- Out << 'V';\r
- VisitType(Arg.getIntegralType());\r
- Out << Arg.getAsIntegral();\r
- break;\r
- }\r
-}\r
-\r
-//===----------------------------------------------------------------------===//\r
-// General purpose USR generation methods.\r
-//===----------------------------------------------------------------------===//\r
-\r
-void USRGenerator::GenObjCClass(StringRef cls) {\r
- Out << "objc(cs)" << cls;\r
-}\r
-\r
-void USRGenerator::GenObjCCategory(StringRef cls, StringRef cat) {\r
- Out << "objc(cy)" << cls << '@' << cat;\r
-}\r
-\r
-void USRGenerator::GenObjCIvar(StringRef ivar) {\r
- Out << '@' << ivar;\r
-}\r
-\r
-void USRGenerator::GenObjCMethod(StringRef meth, bool isInstanceMethod) {\r
- Out << (isInstanceMethod ? "(im)" : "(cm)") << meth;\r
-}\r
-\r
-void USRGenerator::GenObjCProperty(StringRef prop) {\r
- Out << "(py)" << prop;\r
-}\r
-\r
-void USRGenerator::GenObjCProtocol(StringRef prot) {\r
- Out << "objc(pl)" << prot;\r
-}\r
-\r
-//===----------------------------------------------------------------------===//\r
-// API hooks.\r
-//===----------------------------------------------------------------------===//\r
-\r
-static inline StringRef extractUSRSuffix(StringRef s) {\r
- return s.startswith("c:") ? s.substr(2) : "";\r
-}\r
-\r
-bool cxcursor::getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf) {\r
- // Don't generate USRs for things with invalid locations.\r
- if (!D || D->getLocStart().isInvalid())\r
- return true;\r
-\r
- USRGenerator UG(&D->getASTContext(), &Buf);\r
- UG->Visit(const_cast<Decl*>(D));\r
-\r
- if (UG->ignoreResults())\r
- return true;\r
-\r
- return false;\r
-}\r
-\r
-extern "C" {\r
-\r
-CXString clang_getCursorUSR(CXCursor C) {\r
- const CXCursorKind &K = clang_getCursorKind(C);\r
-\r
- if (clang_isDeclaration(K)) {\r
- Decl *D = cxcursor::getCursorDecl(C);\r
- if (!D)\r
- return createCXString("");\r
-\r
- CXTranslationUnit TU = cxcursor::getCursorTU(C);\r
- if (!TU)\r
- return createCXString("");\r
-\r
- CXStringBuf *buf = cxstring::getCXStringBuf(TU);\r
- if (!buf)\r
- return createCXString("");\r
-\r
- bool Ignore = cxcursor::getDeclCursorUSR(D, buf->Data);\r
- if (Ignore) {\r
- disposeCXStringBuf(buf);\r
- return createCXString("");\r
- }\r
-\r
- // Return the C-string, but don't make a copy since it is already in\r
- // the string buffer.\r
- buf->Data.push_back('\0');\r
- return createCXString(buf);\r
- }\r
-\r
- if (K == CXCursor_MacroDefinition) {\r
- CXTranslationUnit TU = cxcursor::getCursorTU(C);\r
- if (!TU)\r
- return createCXString("");\r
-\r
- CXStringBuf *buf = cxstring::getCXStringBuf(TU);\r
- if (!buf)\r
- return createCXString("");\r
-\r
- {\r
- USRGenerator UG(&cxcursor::getCursorASTUnit(C)->getASTContext(),\r
- &buf->Data);\r
- UG << "macro@"\r
- << cxcursor::getCursorMacroDefinition(C)->getName()->getNameStart();\r
- }\r
- buf->Data.push_back('\0');\r
- return createCXString(buf);\r
- }\r
-\r
- return createCXString("");\r
-}\r
-\r
-CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) {\r
- USRGenerator UG;\r
- UG << extractUSRSuffix(clang_getCString(classUSR));\r
- UG->GenObjCIvar(name);\r
- return createCXString(UG.str(), true);\r
-}\r
-\r
-CXString clang_constructUSR_ObjCMethod(const char *name,\r
- unsigned isInstanceMethod,\r
- CXString classUSR) {\r
- USRGenerator UG;\r
- UG << extractUSRSuffix(clang_getCString(classUSR));\r
- UG->GenObjCMethod(name, isInstanceMethod);\r
- return createCXString(UG.str(), true);\r
-}\r
-\r
-CXString clang_constructUSR_ObjCClass(const char *name) {\r
- USRGenerator UG;\r
- UG->GenObjCClass(name);\r
- return createCXString(UG.str(), true);\r
-}\r
-\r
-CXString clang_constructUSR_ObjCProtocol(const char *name) {\r
- USRGenerator UG;\r
- UG->GenObjCProtocol(name);\r
- return createCXString(UG.str(), true);\r
-}\r
-\r
-CXString clang_constructUSR_ObjCCategory(const char *class_name,\r
- const char *category_name) {\r
- USRGenerator UG;\r
- UG->GenObjCCategory(class_name, category_name);\r
- return createCXString(UG.str(), true);\r
-}\r
-\r
-CXString clang_constructUSR_ObjCProperty(const char *property,\r
- CXString classUSR) {\r
- USRGenerator UG;\r
- UG << extractUSRSuffix(clang_getCString(classUSR));\r
- UG->GenObjCProperty(property);\r
- return createCXString(UG.str(), true);\r
-}\r
-\r
-} // end extern "C"\r
+//===- CIndexUSR.cpp - Clang-C Source Indexing Library --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the generation and use of USRs from CXEntities.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CXCursor.h"
+#include "CXString.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::cxstring;
+
+//===----------------------------------------------------------------------===//
+// USR generation.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class USRGenerator : public DeclVisitor<USRGenerator> {
+ OwningPtr<SmallString<128> > OwnedBuf;
+ SmallVectorImpl<char> &Buf;
+ llvm::raw_svector_ostream Out;
+ bool IgnoreResults;
+ ASTContext *Context;
+ bool generatedLoc;
+
+ llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
+
+public:
+ explicit USRGenerator(ASTContext *Ctx = 0, SmallVectorImpl<char> *extBuf = 0)
+ : OwnedBuf(extBuf ? 0 : new SmallString<128>()),
+ Buf(extBuf ? *extBuf : *OwnedBuf.get()),
+ Out(Buf),
+ IgnoreResults(false),
+ Context(Ctx),
+ generatedLoc(false)
+ {
+ // Add the USR space prefix.
+ Out << "c:";
+ }
+
+ StringRef str() {
+ return Out.str();
+ }
+
+ USRGenerator* operator->() { return this; }
+
+ template <typename T>
+ llvm::raw_svector_ostream &operator<<(const T &x) {
+ Out << x;
+ return Out;
+ }
+
+ bool ignoreResults() const { return IgnoreResults; }
+
+ // Visitation methods from generating USRs from AST elements.
+ void VisitDeclContext(DeclContext *D);
+ void VisitFieldDecl(FieldDecl *D);
+ void VisitFunctionDecl(FunctionDecl *D);
+ void VisitNamedDecl(NamedDecl *D);
+ void VisitNamespaceDecl(NamespaceDecl *D);
+ void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+ void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+ void VisitClassTemplateDecl(ClassTemplateDecl *D);
+ void VisitObjCContainerDecl(ObjCContainerDecl *CD);
+ void VisitObjCMethodDecl(ObjCMethodDecl *MD);
+ void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
+ void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
+ void VisitTagDecl(TagDecl *D);
+ void VisitTypedefDecl(TypedefDecl *D);
+ void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
+ void VisitVarDecl(VarDecl *D);
+ void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+ void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+ void VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+ IgnoreResults = true;
+ }
+ void VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ IgnoreResults = true;
+ }
+ void VisitUsingDecl(UsingDecl *D) {
+ IgnoreResults = true;
+ }
+ void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+ IgnoreResults = true;
+ }
+ void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
+ IgnoreResults = true;
+ }
+
+ /// Generate the string component containing the location of the
+ /// declaration.
+ bool GenLoc(const Decl *D);
+
+ /// String generation methods used both by the visitation methods
+ /// and from other clients that want to directly generate USRs. These
+ /// methods do not construct complete USRs (which incorporate the parents
+ /// of an AST element), but only the fragments concerning the AST element
+ /// itself.
+
+ /// Generate a USR for an Objective-C class.
+ void GenObjCClass(StringRef cls);
+ /// Generate a USR for an Objective-C class category.
+ void GenObjCCategory(StringRef cls, StringRef cat);
+ /// Generate a USR fragment for an Objective-C instance variable. The
+ /// complete USR can be created by concatenating the USR for the
+ /// encompassing class with this USR fragment.
+ void GenObjCIvar(StringRef ivar);
+ /// Generate a USR fragment for an Objective-C method.
+ void GenObjCMethod(StringRef sel, bool isInstanceMethod);
+ /// Generate a USR fragment for an Objective-C property.
+ void GenObjCProperty(StringRef prop);
+ /// Generate a USR for an Objective-C protocol.
+ void GenObjCProtocol(StringRef prot);
+
+ void VisitType(QualType T);
+ void VisitTemplateParameterList(const TemplateParameterList *Params);
+ void VisitTemplateName(TemplateName Name);
+ void VisitTemplateArgument(const TemplateArgument &Arg);
+
+ /// Emit a Decl's name using NamedDecl::printName() and return true if
+ /// the decl had no name.
+ bool EmitDeclName(const NamedDecl *D);
+};
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Generating USRs from ASTS.
+//===----------------------------------------------------------------------===//
+
+bool USRGenerator::EmitDeclName(const NamedDecl *D) {
+ Out.flush();
+ const unsigned startSize = Buf.size();
+ D->printName(Out);
+ Out.flush();
+ const unsigned endSize = Buf.size();
+ return startSize == endSize;
+}
+
+static inline bool ShouldGenerateLocation(const NamedDecl *D) {
+ return D->getLinkage() != ExternalLinkage;
+}
+
+void USRGenerator::VisitDeclContext(DeclContext *DC) {
+ if (NamedDecl *D = dyn_cast<NamedDecl>(DC))
+ Visit(D);
+}
+
+void USRGenerator::VisitFieldDecl(FieldDecl *D) {
+ // The USR for an ivar declared in a class extension is based on the
+ // ObjCInterfaceDecl, not the ObjCCategoryDecl.
+ if (ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
+ Visit(ID);
+ else
+ VisitDeclContext(D->getDeclContext());
+ Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");
+ if (EmitDeclName(D)) {
+ // Bit fields can be anonymous.
+ IgnoreResults = true;
+ return;
+ }
+}
+
+void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {
+ if (ShouldGenerateLocation(D) && GenLoc(D))
+ return;
+
+ VisitDeclContext(D->getDeclContext());
+ if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
+ Out << "@FT@";
+ VisitTemplateParameterList(FunTmpl->getTemplateParameters());
+ } else
+ Out << "@F@";
+ D->printName(Out);
+
+ ASTContext &Ctx = *Context;
+ if (!Ctx.getLangOpts().CPlusPlus || D->isExternC())
+ return;
+
+ if (const TemplateArgumentList *
+ SpecArgs = D->getTemplateSpecializationArgs()) {
+ Out << '<';
+ for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) {
+ Out << '#';
+ VisitTemplateArgument(SpecArgs->get(I));
+ }
+ Out << '>';
+ }
+
+ // Mangle in type information for the arguments.
+ for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end();
+ I != E; ++I) {
+ Out << '#';
+ if (ParmVarDecl *PD = *I)
+ VisitType(PD->getType());
+ }
+ if (D->isVariadic())
+ Out << '.';
+ Out << '#';
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (MD->isStatic())
+ Out << 'S';
+ if (unsigned quals = MD->getTypeQualifiers())
+ Out << (char)('0' + quals);
+ }
+}
+
+void USRGenerator::VisitNamedDecl(NamedDecl *D) {
+ VisitDeclContext(D->getDeclContext());
+ Out << "@";
+
+ if (EmitDeclName(D)) {
+ // The string can be empty if the declaration has no name; e.g., it is
+ // the ParmDecl with no name for declaration of a function pointer type,
+ // e.g.: void (*f)(void *);
+ // In this case, don't generate a USR.
+ IgnoreResults = true;
+ }
+}
+
+void USRGenerator::VisitVarDecl(VarDecl *D) {
+ // VarDecls can be declared 'extern' within a function or method body,
+ // but their enclosing DeclContext is the function, not the TU. We need
+ // to check the storage class to correctly generate the USR.
+ if (ShouldGenerateLocation(D) && GenLoc(D))
+ return;
+
+ VisitDeclContext(D->getDeclContext());
+
+ // Variables always have simple names.
+ StringRef s = D->getName();
+
+ // The string can be empty if the declaration has no name; e.g., it is
+ // the ParmDecl with no name for declaration of a function pointer type, e.g.:
+ // void (*f)(void *);
+ // In this case, don't generate a USR.
+ if (s.empty())
+ IgnoreResults = true;
+ else
+ Out << '@' << s;
+}
+
+void USRGenerator::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+ GenLoc(D);
+ return;
+}
+
+void USRGenerator::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+ GenLoc(D);
+ return;
+}
+
+void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
+ if (D->isAnonymousNamespace()) {
+ Out << "@aN";
+ return;
+ }
+
+ VisitDeclContext(D->getDeclContext());
+ if (!IgnoreResults)
+ Out << "@N@" << D->getName();
+}
+
+void USRGenerator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ VisitFunctionDecl(D->getTemplatedDecl());
+}
+
+void USRGenerator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ VisitTagDecl(D->getTemplatedDecl());
+}
+
+void USRGenerator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ VisitDeclContext(D->getDeclContext());
+ if (!IgnoreResults)
+ Out << "@NA@" << D->getName();
+}
+
+void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
+ DeclContext *container = D->getDeclContext();
+ if (ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {
+ Visit(pd);
+ }
+ else {
+ // The USR for a method declared in a class extension or category is based on
+ // the ObjCInterfaceDecl, not the ObjCCategoryDecl.
+ ObjCInterfaceDecl *ID = D->getClassInterface();
+ if (!ID) {
+ IgnoreResults = true;
+ return;
+ }
+ Visit(ID);
+ }
+ // Ideally we would use 'GenObjCMethod', but this is such a hot path
+ // for Objective-C code that we don't want to use
+ // DeclarationName::getAsString().
+ Out << (D->isInstanceMethod() ? "(im)" : "(cm)");
+ DeclarationName N(D->getSelector());
+ N.printName(Out);
+}
+
+void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
+ switch (D->getKind()) {
+ default:
+ llvm_unreachable("Invalid ObjC container.");
+ case Decl::ObjCInterface:
+ case Decl::ObjCImplementation:
+ GenObjCClass(D->getName());
+ break;
+ case Decl::ObjCCategory: {
+ ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
+ ObjCInterfaceDecl *ID = CD->getClassInterface();
+ if (!ID) {
+ // Handle invalid code where the @interface might not
+ // have been specified.
+ // FIXME: We should be able to generate this USR even if the
+ // @interface isn't available.
+ IgnoreResults = true;
+ return;
+ }
+ // Specially handle class extensions, which are anonymous categories.
+ // We want to mangle in the location to uniquely distinguish them.
+ if (CD->IsClassExtension()) {
+ Out << "objc(ext)" << ID->getName() << '@';
+ GenLoc(CD);
+ }
+ else
+ GenObjCCategory(ID->getName(), CD->getName());
+
+ break;
+ }
+ case Decl::ObjCCategoryImpl: {
+ ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
+ ObjCInterfaceDecl *ID = CD->getClassInterface();
+ if (!ID) {
+ // Handle invalid code where the @interface might not
+ // have been specified.
+ // FIXME: We should be able to generate this USR even if the
+ // @interface isn't available.
+ IgnoreResults = true;
+ return;
+ }
+ GenObjCCategory(ID->getName(), CD->getName());
+ break;
+ }
+ case Decl::ObjCProtocol:
+ GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName());
+ break;
+ }
+}
+
+void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
+ // The USR for a property declared in a class extension or category is based
+ // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
+ if (ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
+ Visit(ID);
+ else
+ Visit(cast<Decl>(D->getDeclContext()));
+ GenObjCProperty(D->getName());
+}
+
+void USRGenerator::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+ if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
+ VisitObjCPropertyDecl(PD);
+ return;
+ }
+
+ IgnoreResults = true;
+}
+
+void USRGenerator::VisitTagDecl(TagDecl *D) {
+ // Add the location of the tag decl to handle resolution across
+ // translation units.
+ if (ShouldGenerateLocation(D) && GenLoc(D))
+ return;
+
+ D = D->getCanonicalDecl();
+ VisitDeclContext(D->getDeclContext());
+
+ bool AlreadyStarted = false;
+ if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
+ if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
+ AlreadyStarted = true;
+
+ switch (D->getTagKind()) {
+ case TTK_Interface:
+ case TTK_Struct: Out << "@ST"; break;
+ case TTK_Class: Out << "@CT"; break;
+ case TTK_Union: Out << "@UT"; break;
+ case TTK_Enum: llvm_unreachable("enum template");
+ }
+ VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
+ } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
+ AlreadyStarted = true;
+
+ switch (D->getTagKind()) {
+ case TTK_Interface:
+ case TTK_Struct: Out << "@SP"; break;
+ case TTK_Class: Out << "@CP"; break;
+ case TTK_Union: Out << "@UP"; break;
+ case TTK_Enum: llvm_unreachable("enum partial specialization");
+ }
+ VisitTemplateParameterList(PartialSpec->getTemplateParameters());
+ }
+ }
+
+ if (!AlreadyStarted) {
+ switch (D->getTagKind()) {
+ case TTK_Interface:
+ case TTK_Struct: Out << "@S"; break;
+ case TTK_Class: Out << "@C"; break;
+ case TTK_Union: Out << "@U"; break;
+ case TTK_Enum: Out << "@E"; break;
+ }
+ }
+
+ Out << '@';
+ Out.flush();
+ assert(Buf.size() > 0);
+ const unsigned off = Buf.size() - 1;
+
+ if (EmitDeclName(D)) {
+ if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
+ Buf[off] = 'A';
+ Out << '@' << *TD;
+ }
+ else
+ Buf[off] = 'a';
+ }
+
+ // For a class template specialization, mangle the template arguments.
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs();
+ Out << '>';
+ for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+ Out << '#';
+ VisitTemplateArgument(Args.get(I));
+ }
+ }
+}
+
+void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
+ if (ShouldGenerateLocation(D) && GenLoc(D))
+ return;
+ DeclContext *DC = D->getDeclContext();
+ if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
+ Visit(DCN);
+ Out << "@T@";
+ Out << D->getName();
+}
+
+void USRGenerator::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ GenLoc(D);
+ return;
+}
+
+bool USRGenerator::GenLoc(const Decl *D) {
+ if (generatedLoc)
+ return IgnoreResults;
+ generatedLoc = true;
+
+ // Guard against null declarations in invalid code.
+ if (!D) {
+ IgnoreResults = true;
+ return true;
+ }
+
+ // Use the location of canonical decl.
+ D = D->getCanonicalDecl();
+
+ const SourceManager &SM = Context->getSourceManager();
+ SourceLocation L = D->getLocStart();
+ if (L.isInvalid()) {
+ IgnoreResults = true;
+ return true;
+ }
+ L = SM.getExpansionLoc(L);
+ const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(L);
+ const FileEntry *FE = SM.getFileEntryForID(Decomposed.first);
+ if (FE) {
+ Out << llvm::sys::path::filename(FE->getName());
+ }
+ else {
+ // This case really isn't interesting.
+ IgnoreResults = true;
+ return true;
+ }
+ // Use the offest into the FileID to represent the location. Using
+ // a line/column can cause us to look back at the original source file,
+ // which is expensive.
+ Out << '@' << Decomposed.second;
+ return IgnoreResults;
+}
+
+void USRGenerator::VisitType(QualType T) {
+ // This method mangles in USR information for types. It can possibly
+ // just reuse the naming-mangling logic used by codegen, although the
+ // requirements for USRs might not be the same.
+ ASTContext &Ctx = *Context;
+
+ do {
+ T = Ctx.getCanonicalType(T);
+ Qualifiers Q = T.getQualifiers();
+ unsigned qVal = 0;
+ if (Q.hasConst())
+ qVal |= 0x1;
+ if (Q.hasVolatile())
+ qVal |= 0x2;
+ if (Q.hasRestrict())
+ qVal |= 0x4;
+ if(qVal)
+ Out << ((char) ('0' + qVal));
+
+ // Mangle in ObjC GC qualifiers?
+
+ if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
+ Out << 'P';
+ T = Expansion->getPattern();
+ }
+
+ if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
+ unsigned char c = '\0';
+ switch (BT->getKind()) {
+ case BuiltinType::Void:
+ c = 'v'; break;
+ case BuiltinType::Bool:
+ c = 'b'; break;
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ c = 'c'; break;
+ case BuiltinType::Char16:
+ c = 'q'; break;
+ case BuiltinType::Char32:
+ c = 'w'; break;
+ case BuiltinType::UShort:
+ c = 's'; break;
+ case BuiltinType::UInt:
+ c = 'i'; break;
+ case BuiltinType::ULong:
+ c = 'l'; break;
+ case BuiltinType::ULongLong:
+ c = 'k'; break;
+ case BuiltinType::UInt128:
+ c = 'j'; break;
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ c = 'C'; break;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ c = 'W'; break;
+ case BuiltinType::Short:
+ c = 'S'; break;
+ case BuiltinType::Int:
+ c = 'I'; break;
+ case BuiltinType::Long:
+ c = 'L'; break;
+ case BuiltinType::LongLong:
+ c = 'K'; break;
+ case BuiltinType::Int128:
+ c = 'J'; break;
+ case BuiltinType::Half:
+ c = 'h'; break;
+ case BuiltinType::Float:
+ c = 'f'; break;
+ case BuiltinType::Double:
+ c = 'd'; break;
+ case BuiltinType::LongDouble:
+ c = 'D'; break;
+ case BuiltinType::NullPtr:
+ c = 'n'; break;
+#define BUILTIN_TYPE(Id, SingletonId)
+#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
+#include "clang/AST/BuiltinTypes.def"
+ case BuiltinType::Dependent:
+ IgnoreResults = true;
+ return;
+ case BuiltinType::ObjCId:
+ c = 'o'; break;
+ case BuiltinType::ObjCClass:
+ c = 'O'; break;
+ case BuiltinType::ObjCSel:
+ c = 'e'; break;
+ }
+ Out << c;
+ return;
+ }
+
+ // If we have already seen this (non-built-in) type, use a substitution
+ // encoding.
+ llvm::DenseMap<const Type *, unsigned>::iterator Substitution
+ = TypeSubstitutions.find(T.getTypePtr());
+ if (Substitution != TypeSubstitutions.end()) {
+ Out << 'S' << Substitution->second << '_';
+ return;
+ } else {
+ // Record this as a substitution.
+ unsigned Number = TypeSubstitutions.size();
+ TypeSubstitutions[T.getTypePtr()] = Number;
+ }
+
+ if (const PointerType *PT = T->getAs<PointerType>()) {
+ Out << '*';
+ T = PT->getPointeeType();
+ continue;
+ }
+ if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
+ Out << '&';
+ T = RT->getPointeeType();
+ continue;
+ }
+ if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
+ Out << 'F';
+ VisitType(FT->getResultType());
+ for (FunctionProtoType::arg_type_iterator
+ I = FT->arg_type_begin(), E = FT->arg_type_end(); I!=E; ++I) {
+ VisitType(*I);
+ }
+ if (FT->isVariadic())
+ Out << '.';
+ return;
+ }
+ if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
+ Out << 'B';
+ T = BT->getPointeeType();
+ continue;
+ }
+ if (const ComplexType *CT = T->getAs<ComplexType>()) {
+ Out << '<';
+ T = CT->getElementType();
+ continue;
+ }
+ if (const TagType *TT = T->getAs<TagType>()) {
+ Out << '$';
+ VisitTagDecl(TT->getDecl());
+ return;
+ }
+ if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
+ Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
+ return;
+ }
+ if (const TemplateSpecializationType *Spec
+ = T->getAs<TemplateSpecializationType>()) {
+ Out << '>';
+ VisitTemplateName(Spec->getTemplateName());
+ Out << Spec->getNumArgs();
+ for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+ VisitTemplateArgument(Spec->getArg(I));
+ return;
+ }
+
+ // Unhandled type.
+ Out << ' ';
+ break;
+ } while (true);
+}
+
+void USRGenerator::VisitTemplateParameterList(
+ const TemplateParameterList *Params) {
+ if (!Params)
+ return;
+ Out << '>' << Params->size();
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ Out << '#';
+ if (isa<TemplateTypeParmDecl>(*P)) {
+ if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
+ Out<< 'p';
+ Out << 'T';
+ continue;
+ }
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+ if (NTTP->isParameterPack())
+ Out << 'p';
+ Out << 'N';
+ VisitType(NTTP->getType());
+ continue;
+ }
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+ if (TTP->isParameterPack())
+ Out << 'p';
+ Out << 't';
+ VisitTemplateParameterList(TTP->getTemplateParameters());
+ }
+}
+
+void USRGenerator::VisitTemplateName(TemplateName Name) {
+ if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(Template)) {
+ Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
+ return;
+ }
+
+ Visit(Template);
+ return;
+ }
+
+ // FIXME: Visit dependent template names.
+}
+
+void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ break;
+
+ case TemplateArgument::Declaration:
+ Visit(Arg.getAsDecl());
+ break;
+
+ case TemplateArgument::NullPtr:
+ break;
+
+ case TemplateArgument::TemplateExpansion:
+ Out << 'P'; // pack expansion of...
+ // Fall through
+ case TemplateArgument::Template:
+ VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
+ break;
+
+ case TemplateArgument::Expression:
+ // FIXME: Visit expressions.
+ break;
+
+ case TemplateArgument::Pack:
+ Out << 'p' << Arg.pack_size();
+ for (TemplateArgument::pack_iterator P = Arg.pack_begin(), PEnd = Arg.pack_end();
+ P != PEnd; ++P)
+ VisitTemplateArgument(*P);
+ break;
+
+ case TemplateArgument::Type:
+ VisitType(Arg.getAsType());
+ break;
+
+ case TemplateArgument::Integral:
+ Out << 'V';
+ VisitType(Arg.getIntegralType());
+ Out << Arg.getAsIntegral();
+ break;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// General purpose USR generation methods.
+//===----------------------------------------------------------------------===//
+
+void USRGenerator::GenObjCClass(StringRef cls) {
+ Out << "objc(cs)" << cls;
+}
+
+void USRGenerator::GenObjCCategory(StringRef cls, StringRef cat) {
+ Out << "objc(cy)" << cls << '@' << cat;
+}
+
+void USRGenerator::GenObjCIvar(StringRef ivar) {
+ Out << '@' << ivar;
+}
+
+void USRGenerator::GenObjCMethod(StringRef meth, bool isInstanceMethod) {
+ Out << (isInstanceMethod ? "(im)" : "(cm)") << meth;
+}
+
+void USRGenerator::GenObjCProperty(StringRef prop) {
+ Out << "(py)" << prop;
+}
+
+void USRGenerator::GenObjCProtocol(StringRef prot) {
+ Out << "objc(pl)" << prot;
+}
+
+//===----------------------------------------------------------------------===//
+// API hooks.
+//===----------------------------------------------------------------------===//
+
+static inline StringRef extractUSRSuffix(StringRef s) {
+ return s.startswith("c:") ? s.substr(2) : "";
+}
+
+bool cxcursor::getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf) {
+ // Don't generate USRs for things with invalid locations.
+ if (!D || D->getLocStart().isInvalid())
+ return true;
+
+ USRGenerator UG(&D->getASTContext(), &Buf);
+ UG->Visit(const_cast<Decl*>(D));
+
+ if (UG->ignoreResults())
+ return true;
+
+ return false;
+}
+
+extern "C" {
+
+CXString clang_getCursorUSR(CXCursor C) {
+ const CXCursorKind &K = clang_getCursorKind(C);
+
+ if (clang_isDeclaration(K)) {
+ Decl *D = cxcursor::getCursorDecl(C);
+ if (!D)
+ return createCXString("");
+
+ CXTranslationUnit TU = cxcursor::getCursorTU(C);
+ if (!TU)
+ return createCXString("");
+
+ CXStringBuf *buf = cxstring::getCXStringBuf(TU);
+ if (!buf)
+ return createCXString("");
+
+ bool Ignore = cxcursor::getDeclCursorUSR(D, buf->Data);
+ if (Ignore) {
+ disposeCXStringBuf(buf);
+ return createCXString("");
+ }
+
+ // Return the C-string, but don't make a copy since it is already in
+ // the string buffer.
+ buf->Data.push_back('\0');
+ return createCXString(buf);
+ }
+
+ if (K == CXCursor_MacroDefinition) {
+ CXTranslationUnit TU = cxcursor::getCursorTU(C);
+ if (!TU)
+ return createCXString("");
+
+ CXStringBuf *buf = cxstring::getCXStringBuf(TU);
+ if (!buf)
+ return createCXString("");
+
+ {
+ USRGenerator UG(&cxcursor::getCursorASTUnit(C)->getASTContext(),
+ &buf->Data);
+ UG << "macro@"
+ << cxcursor::getCursorMacroDefinition(C)->getName()->getNameStart();
+ }
+ buf->Data.push_back('\0');
+ return createCXString(buf);
+ }
+
+ return createCXString("");
+}
+
+CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) {
+ USRGenerator UG;
+ UG << extractUSRSuffix(clang_getCString(classUSR));
+ UG->GenObjCIvar(name);
+ return createCXString(UG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCMethod(const char *name,
+ unsigned isInstanceMethod,
+ CXString classUSR) {
+ USRGenerator UG;
+ UG << extractUSRSuffix(clang_getCString(classUSR));
+ UG->GenObjCMethod(name, isInstanceMethod);
+ return createCXString(UG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCClass(const char *name) {
+ USRGenerator UG;
+ UG->GenObjCClass(name);
+ return createCXString(UG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCProtocol(const char *name) {
+ USRGenerator UG;
+ UG->GenObjCProtocol(name);
+ return createCXString(UG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCCategory(const char *class_name,
+ const char *category_name) {
+ USRGenerator UG;
+ UG->GenObjCCategory(class_name, category_name);
+ return createCXString(UG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCProperty(const char *property,
+ CXString classUSR) {
+ USRGenerator UG;
+ UG << extractUSRSuffix(clang_getCString(classUSR));
+ UG->GenObjCProperty(property);
+ return createCXString(UG.str(), true);
+}
+
+} // end extern "C"