[cfe-commits] r163013 - in /cfe/trunk: include/clang-c/ include/clang/AST/ include/clang/Basic/ include/clang/Sema/ lib/AST/ lib/CodeGen/ lib/Parse/ lib/Sema/ lib/Serialization/ test/Parser/ tools/libclang/

David Blaikie dblaikie at gmail.com
Fri Aug 31 14:57:42 PDT 2012


On Fri, Aug 31, 2012 at 11:45 AM, Joao Matos <ripzonetriton at gmail.com> wrote:
> Author: triton
> Date: Fri Aug 31 13:45:21 2012
> New Revision: 163013
>
> URL: http://llvm.org/viewvc/llvm-project?rev=163013&view=rev
> Log:
> Improved MSVC __interface support by adding first class support for it, instead of aliasing to "struct" which had some incorrect behaviour. Patch by David Robins.
>
> Modified:
>     cfe/trunk/include/clang-c/Index.h
>     cfe/trunk/include/clang/AST/CanonicalType.h
>     cfe/trunk/include/clang/AST/Decl.h
>     cfe/trunk/include/clang/AST/DeclCXX.h
>     cfe/trunk/include/clang/AST/Type.h
>     cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
>     cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>     cfe/trunk/include/clang/Basic/Specifiers.h
>     cfe/trunk/include/clang/Basic/TokenKinds.def
>     cfe/trunk/include/clang/Sema/DeclSpec.h
>     cfe/trunk/lib/AST/DeclCXX.cpp
>     cfe/trunk/lib/AST/MicrosoftMangle.cpp
>     cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
>     cfe/trunk/lib/AST/Type.cpp
>     cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
>     cfe/trunk/lib/Parse/ParseDecl.cpp
>     cfe/trunk/lib/Parse/ParseDeclCXX.cpp
>     cfe/trunk/lib/Sema/DeclSpec.cpp
>     cfe/trunk/lib/Sema/SemaCodeComplete.cpp
>     cfe/trunk/lib/Sema/SemaDecl.cpp
>     cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>     cfe/trunk/lib/Sema/SemaExprCXX.cpp
>     cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
>     cfe/trunk/lib/Sema/SemaType.cpp
>     cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
>     cfe/trunk/test/Parser/MicrosoftExtensions.cpp
>     cfe/trunk/tools/libclang/CIndexCXX.cpp
>     cfe/trunk/tools/libclang/CIndexUSRs.cpp
>     cfe/trunk/tools/libclang/IndexingContext.cpp
>
> Modified: cfe/trunk/include/clang-c/Index.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang-c/Index.h (original)
> +++ cfe/trunk/include/clang-c/Index.h Fri Aug 31 13:45:21 2012
> @@ -4962,13 +4962,14 @@
>    CXIdxEntity_CXXStaticVariable     = 19,
>    CXIdxEntity_CXXStaticMethod       = 20,
>    CXIdxEntity_CXXInstanceMethod     = 21,
> -  CXIdxEntity_CXXConstructor        = 22,
> -  CXIdxEntity_CXXDestructor         = 23,
> -  CXIdxEntity_CXXConversionFunction = 24,
> -  CXIdxEntity_CXXTypeAlias          = 25
> -
> -} CXIdxEntityKind;
> -
> +  CXIdxEntity_CXXConstructor        = 22,
> +  CXIdxEntity_CXXDestructor         = 23,
> +  CXIdxEntity_CXXConversionFunction = 24,
> +  CXIdxEntity_CXXTypeAlias          = 25,
> +  CXIdxEntity_CXXInterface          = 26

This caused a build break/warning:

/home/blaikie/local/Development/llvm/src/tools/clang/tools/c-index-test/c-index-test.c:2183:11:
error: enumeration value 'CXIdxEntity_CXXInterface' not handled in
switch [-Werror,-Wswitch]
  switch (kind) {
          ^

I've fixed this in r163025.

> +
> +} CXIdxEntityKind;
> +
>  typedef enum {
>    CXIdxEntityLang_None = 0,
>    CXIdxEntityLang_C    = 1,
>
> Modified: cfe/trunk/include/clang/AST/CanonicalType.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CanonicalType.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/CanonicalType.h (original)
> +++ cfe/trunk/include/clang/AST/CanonicalType.h Fri Aug 31 13:45:21 2012
> @@ -276,6 +276,7 @@
>    LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType)
>    LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType)
>    LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType)
> +  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isInterfaceType)
>    LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType)
>    LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType)
>    LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType)
>
> Modified: cfe/trunk/include/clang/AST/Decl.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Decl.h (original)
> +++ cfe/trunk/include/clang/AST/Decl.h Fri Aug 31 13:45:21 2012
> @@ -2448,7 +2448,7 @@
>  private:
>    // FIXME: This can be packed into the bitfields in Decl.
>    /// TagDeclKind - The TagKind enum.
> -  unsigned TagDeclKind : 2;
> +  unsigned TagDeclKind : 3;
>
>    /// IsCompleteDefinition - True if this is a definition ("struct foo
>    /// {};"), false if it is a declaration ("struct foo;").  It is not
> @@ -2625,6 +2625,7 @@
>    void setTagKind(TagKind TK) { TagDeclKind = TK; }
>
>    bool isStruct() const { return getTagKind() == TTK_Struct; }
> +  bool isInterface() const { return getTagKind() == TTK_Interface; }
>    bool isClass()  const { return getTagKind() == TTK_Class; }
>    bool isUnion()  const { return getTagKind() == TTK_Union; }
>    bool isEnum()   const { return getTagKind() == TTK_Enum; }
>
> Modified: cfe/trunk/include/clang/AST/DeclCXX.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/DeclCXX.h (original)
> +++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Aug 31 13:45:21 2012
> @@ -1553,13 +1553,15 @@
>    bool isVolatile() { return getType()->castAs<FunctionType>()->isVolatile(); }
>
>    bool isVirtual() const {
> -    CXXMethodDecl *CD =
> -      cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl());
> -
> -    if (CD->isVirtualAsWritten())
> -      return true;
> -
> -    return (CD->begin_overridden_methods() != CD->end_overridden_methods());
> +    CXXMethodDecl *CD =
> +      cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl());
> +
> +    // Methods declared in interfaces are automatically (pure) virtual
> +    if (CD->isVirtualAsWritten() ||
> +        CD->getParent()->getTagKind() == TTK_Interface)
> +      return true;
> +
> +    return (CD->begin_overridden_methods() != CD->end_overridden_methods());
>    }
>
>    /// \brief Determine whether this is a usual deallocation function
>
> Modified: cfe/trunk/include/clang/AST/Type.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Type.h (original)
> +++ cfe/trunk/include/clang/AST/Type.h Fri Aug 31 13:45:21 2012
> @@ -1512,6 +1512,7 @@
>    bool isRecordType() const;
>    bool isClassType() const;
>    bool isStructureType() const;
> +  bool isInterfaceType() const;
>    bool isStructureOrClassType() const;
>    bool isUnionType() const;
>    bool isComplexIntegerType() const;            // GCC _Complex integer type.
> @@ -3796,6 +3797,8 @@
>  enum TagTypeKind {
>    /// \brief The "struct" keyword.
>    TTK_Struct,
> +  /// \brief The "__interface" keyword.
> +  TTK_Interface,
>    /// \brief The "union" keyword.
>    TTK_Union,
>    /// \brief The "class" keyword.
> @@ -3809,6 +3812,8 @@
>  enum ElaboratedTypeKeyword {
>    /// \brief The "struct" keyword introduces the elaborated-type-specifier.
>    ETK_Struct,
> +  /// \brief The "__interface" keyword introduces the elaborated-type-specifier.
> +  ETK_Interface,
>    /// \brief The "union" keyword introduces the elaborated-type-specifier.
>    ETK_Union,
>    /// \brief The "class" keyword introduces the elaborated-type-specifier.
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Fri Aug 31 13:45:21 2012
> @@ -134,13 +134,13 @@
>  def err_odr_function_type_inconsistent : Error<
>    "external function %0 declared with incompatible types in different "
>    "translation units (%1 vs. %2)">;
> -def warn_odr_tag_type_inconsistent : Warning<
> -  "type %0 has incompatible definitions in different translation units">;
> -def note_odr_tag_kind_here: Note<
> -  "%0 is a %select{struct|union|class|enum}1 here">;
> -def note_odr_field : Note<"field %0 has type %1 here">;
> -def note_odr_missing_field : Note<"no corresponding field here">;
> -def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">;
> +def warn_odr_tag_type_inconsistent : Warning<
> +  "type %0 has incompatible definitions in different translation units">;
> +def note_odr_tag_kind_here: Note<
> +  "%0 is a %select{struct|interface|union|class|enum}1 here">;
> +def note_odr_field : Note<"field %0 has type %1 here">;
> +def note_odr_missing_field : Note<"no corresponding field here">;
> +def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">;
>  def note_odr_not_bit_field : Note<"field %0 is not a bit-field">;
>  def note_odr_base : Note<"class has base type %0">;
>  def note_odr_virtual_base : Note<
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Fri Aug 31 13:45:21 2012
> @@ -573,13 +573,13 @@
>  def err_typename_refers_to_non_type_template : Error<
>    "typename specifier refers to a non-template">;
>  def err_expected_type_name_after_typename : Error<
> -  "expected an identifier or template-id after '::'">;
> -def err_explicit_spec_non_template : Error<
> -  "explicit %select{specialization|instantiation}0 of non-template "
> -  "%select{class|struct|union}1 %2">;
> -
> -def err_default_template_template_parameter_not_template : Error<
> -  "default template argument for a template template parameter must be a class "
> +  "expected an identifier or template-id after '::'">;
> +def err_explicit_spec_non_template : Error<
> +  "explicit %select{specialization|instantiation}0 of non-template "
> +  "%select{class|struct|union|interface}1 %2">;
> +
> +def err_default_template_template_parameter_not_template : Error<
> +  "default template argument for a template template parameter must be a class "
>    "template">;
>
>  def err_ctor_init_missing_comma : Error<
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Aug 31 13:45:21 2012
> @@ -793,16 +793,17 @@
>    "friends cannot be members of the declaring class">;
>  def warn_cxx98_compat_friend_is_member : Warning<
>    "friend declaration naming a member of the declaring class is incompatible "
> -  "with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
> -def ext_unelaborated_friend_type : ExtWarn<
> -  "unelaborated friend declaration is a C++11 extension; specify "
> -  "'%select{struct|union|class|enum}0' to befriend %1">, InGroup<CXX11>;
> -def warn_cxx98_compat_unelaborated_friend_type : Warning<
> -  "befriending %1 without '%select{struct|union|class|enum}0' keyword is "
> -  "incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
> -def err_qualified_friend_not_found : Error<
> -  "no function named %0 with type %1 was found in the specified scope">;
> -def err_introducing_special_friend : Error<
> +  "with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
> +def ext_unelaborated_friend_type : ExtWarn<
> +  "unelaborated friend declaration is a C++11 extension; specify "
> +  "'%select{struct|interface|union|class|enum}0' to befriend %1">,
> +  InGroup<CXX11>;
> +def warn_cxx98_compat_unelaborated_friend_type : Warning<
> +  "befriending %1 without '%select{struct|interface|union|class|enum}0' "
> +  "keyword is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
> +def err_qualified_friend_not_found : Error<
> +  "no function named %0 with type %1 was found in the specified scope">;
> +def err_introducing_special_friend : Error<
>    "must use a qualified name when declaring a %select{constructor|"
>    "destructor|conversion operator}0 as a friend">;
>  def err_tagless_friend_type_template : Error<
> @@ -1114,14 +1115,14 @@
>  def err_constructor_return_type : Error<
>    "constructor cannot have a return type">;
>  def err_constructor_redeclared : Error<"constructor cannot be redeclared">;
> -def err_constructor_byvalue_arg : Error<
> -  "copy constructor must pass its first argument by reference">;
> -def warn_no_constructor_for_refconst : Warning<
> -  "%select{struct|union|class|enum}0 %1 does not declare any constructor to "
> -  "initialize its non-modifiable members">;
> -def note_refconst_member_not_initialized : Note<
> -  "%select{const|reference}0 member %1 will never be initialized">;
> -def ext_ms_explicit_constructor_call : ExtWarn<
> +def err_constructor_byvalue_arg : Error<
> +  "copy constructor must pass its first argument by reference">;
> +def warn_no_constructor_for_refconst : Warning<
> +  "%select{struct|interface|union|class|enum}0 %1 does not declare any "
> +  "constructor to initialize its non-modifiable members">;
> +def note_refconst_member_not_initialized : Note<
> +  "%select{const|reference}0 member %1 will never be initialized">;
> +def ext_ms_explicit_constructor_call : ExtWarn<
>    "explicit constructor calls are a Microsoft extension">, InGroup<Microsoft>;
>
>  // C++ destructors
> @@ -1308,15 +1309,16 @@
>  def err_illegal_decl_array_of_auto : Error<
>    "'%0' declared as array of %1">;
>  def err_new_array_of_auto : Error<
> -  "cannot allocate array of 'auto'">;
> -def err_auto_not_allowed : Error<
> -  "'auto' not allowed %select{in function prototype|in non-static struct member"
> -  "|in non-static union member|in non-static class member|in exception declaration"
> -  "|in template parameter|in block literal|in template argument"
> -  "|in typedef|in type alias|in function return type|here}0">;
> -def err_auto_var_requires_init : Error<
> -  "declaration of variable %0 with type %1 requires an initializer">;
> -def err_auto_new_requires_ctor_arg : Error<
> +  "cannot allocate array of 'auto'">;
> +def err_auto_not_allowed : Error<
> +  "'auto' not allowed %select{in function prototype|in non-static struct member"
> +  "|in non-static union member|in non-static class member|in interface member"
> +  "|in exception declaration|in template parameter|in block literal"
> +  "|in template argument|in typedef|in type alias|in function return type"
> +  "|here}0">;
> +def err_auto_var_requires_init : Error<
> +  "declaration of variable %0 with type %1 requires an initializer">;
> +def err_auto_new_requires_ctor_arg : Error<
>    "new expression for type %0 requires a constructor argument">;
>  def err_auto_new_requires_parens : Error<
>    "new expression for type %0 cannot use list-initialization">;
> @@ -1436,13 +1438,13 @@
>    "'constexpr' specifier is incompatible with C++98">,
>    InGroup<CXX98Compat>, DefaultIgnore;
>  def err_invalid_constexpr : Error<
> -  "%select{function parameter|typedef|non-static data member}0 "
> -  "cannot be constexpr">;
> -def err_constexpr_tag : Error<
> -  "%select{class|struct|union|enum}0 cannot be marked constexpr">;
> -def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">;
> -def err_constexpr_no_declarators : Error<
> -  "constexpr can only be used in variable and function declarations">;
> +  "%select{function parameter|typedef|non-static data member}0 "
> +  "cannot be constexpr">;
> +def err_constexpr_tag : Error<
> +  "%select{class|struct|interface|union|enum}0 cannot be marked constexpr">;
> +def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">;
> +def err_constexpr_no_declarators : Error<
> +  "constexpr can only be used in variable and function declarations">;
>  def err_invalid_constexpr_var_decl : Error<
>    "constexpr variable declaration must be a definition">;
>  def err_constexpr_static_mem_var_requires_init : Error<
> @@ -1454,17 +1456,18 @@
>  def err_constexpr_redecl_mismatch : Error<
>    "%select{non-constexpr declaration of %0 follows constexpr declaration"
>    "|constexpr declaration of %0 follows non-constexpr declaration}1">;
> -def err_constexpr_virtual : Error<"virtual function cannot be constexpr">;
> -def err_constexpr_virtual_base : Error<
> -  "constexpr %select{member function|constructor}0 not allowed in "
> -  "%select{class|struct}1 with virtual base %plural{1:class|:classes}2">;
> -def note_non_literal_incomplete : Note<
> -  "incomplete type %0 is not a literal type">;
> -def note_non_literal_virtual_base : Note<"%select{class|struct}0 with virtual "
> -  "base %plural{1:class|:classes}1 is not a literal type">;
> -def note_constexpr_virtual_base_here : Note<"virtual base class declared here">;
> -def err_constexpr_non_literal_return : Error<
> -  "constexpr function's return type %0 is not a literal type">;
> +def err_constexpr_virtual : Error<"virtual function cannot be constexpr">;
> +def err_constexpr_virtual_base : Error<
> +  "constexpr %select{member function|constructor}0 not allowed in "
> +  "%select{struct|interface|class}1 with virtual base "
> +  "%plural{1:class|:classes}2">;
> +def note_non_literal_incomplete : Note<
> +  "incomplete type %0 is not a literal type">;
> +def note_non_literal_virtual_base : Note<"%select{struct|interface|class}0 "
> +  "with virtual base %plural{1:class|:classes}1 is not a literal type">;
> +def note_constexpr_virtual_base_here : Note<"virtual base class declared here">;
> +def err_constexpr_non_literal_return : Error<
> +  "constexpr function's return type %0 is not a literal type">;
>  def err_constexpr_non_literal_param : Error<
>    "constexpr %select{function|constructor}1's %ordinal0 parameter type %2 is "
>    "not a literal type">;
> @@ -1697,13 +1700,15 @@
>    "__declspec attribute %0 is not supported">,
>    InGroup<IgnoredAttributes>;
>  def warn_attribute_invalid_on_stmt : Warning<
> -  "attribute %0 cannot be specified on a statement">,
> -  InGroup<IgnoredAttributes>;
> -def warn_declspec_attribute_ignored : Warning<
> -  "attribute %0 is ignored, place it after \"%select{class|struct|union|enum}1\" to apply attribute to type declaration">, InGroup<IgnoredAttributes>;
> -def warn_attribute_precede_definition : Warning<
> -  "attribute declaration must precede definition">,
> -  InGroup<IgnoredAttributes>;
> +  "attribute %0 cannot be specified on a statement">,
> +  InGroup<IgnoredAttributes>;
> +def warn_declspec_attribute_ignored : Warning<
> +  "attribute %0 is ignored, place it after "
> +  "\"%select{class|struct|union|interface|enum}1\" to apply attribute to "
> +  "type declaration">, InGroup<IgnoredAttributes>;
> +def warn_attribute_precede_definition : Warning<
> +  "attribute declaration must precede definition">,
> +  InGroup<IgnoredAttributes>;
>  def warn_attribute_void_function_method : Warning<
>    "attribute %0 cannot be applied to "
>    "%select{functions|Objective-C method}1 without return value">,
> @@ -3178,30 +3183,31 @@
>  def err_tag_reference_non_tag : Error<
>    "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template|a type alias template}0">;
>  def err_tag_reference_conflict : Error<
> -  "implicit declaration introduced by elaborated type conflicts with "
> -  "%select{a declaration|a typedef|a type alias|a template}0 of the same name">;
> -def err_dependent_tag_decl : Error<
> -  "%select{declaration|definition}0 of %select{struct|union|class|enum}1 "
> -  "in a dependent scope">;
> -def err_tag_definition_of_typedef : Error<
> -  "definition of type %0 conflicts with %select{typedef|type alias}1 of the same name">;
> -def err_conflicting_types : Error<"conflicting types for %0">;
> +  "implicit declaration introduced by elaborated type conflicts with "
> +  "%select{a declaration|a typedef|a type alias|a template}0 of the same name">;
> +def err_dependent_tag_decl : Error<
> +  "%select{declaration|definition}0 of "
> +  "%select{struct|interface|union|class|enum}1 in a dependent scope">;
> +def err_tag_definition_of_typedef : Error<
> +  "definition of type %0 conflicts with %select{typedef|type alias}1 of the same name">;
> +def err_conflicting_types : Error<"conflicting types for %0">;
>  def err_nested_redefinition : Error<"nested redefinition of %0">;
> -def err_use_with_wrong_tag : Error<
> -  "use of %0 with tag type that does not match previous declaration">;
> -def warn_struct_class_tag_mismatch : Warning<
> -    "%select{struct|class}0%select{| template}1 %2 was previously declared "
> -    "as a %select{class|struct}0%select{| template}1">,
> -    InGroup<MismatchedTags>, DefaultIgnore;
> -def warn_struct_class_previous_tag_mismatch : Warning<
> -    "%2 defined as a %select{struct|class}0%select{| template}1 here but "
> -    "previously declared as a %select{class|struct}0%select{| template}1">,
> -     InGroup<MismatchedTags>, DefaultIgnore;
> -def note_struct_class_suggestion : Note<
> -    "did you mean %select{struct|class}0 here?">;
> -def ext_forward_ref_enum : Extension<
> -  "ISO C forbids forward references to 'enum' types">;
> -def err_forward_ref_enum : Error<
> +def err_use_with_wrong_tag : Error<
> +  "use of %0 with tag type that does not match previous declaration">;
> +def warn_struct_class_tag_mismatch : Warning<
> +    "%select{struct|interface|class}0%select{| template}1 %2 was previously "
> +    "declared as a %select{struct|interface|class}3%select{| template}1">,
> +    InGroup<MismatchedTags>, DefaultIgnore;
> +def warn_struct_class_previous_tag_mismatch : Warning<
> +    "%2 defined as %select{a struct|an interface|a class}0%select{| template}1 "
> +    "here but previously declared as "
> +    "%select{a struct|an interface|a class}3%select{| template}1">,
> +     InGroup<MismatchedTags>, DefaultIgnore;
> +def note_struct_class_suggestion : Note<
> +    "did you mean %select{struct|interface|class}0 here?">;
> +def ext_forward_ref_enum : Extension<
> +  "ISO C forbids forward references to 'enum' types">;
> +def err_forward_ref_enum : Error<
>    "ISO C++ forbids forward references to 'enum' types">;
>  def ext_ms_forward_ref_enum : Extension<
>    "forward references to 'enum' types are a Microsoft extension">, InGroup<Microsoft>;
> @@ -3239,17 +3245,19 @@
>  def warn_array_new_too_large : Warning<"array is too large (%0 elements)">,
>    // FIXME PR11644: ", will throw std::bad_array_new_length at runtime"
>    InGroup<DiagGroup<"bad-array-new-length">>;
> -
> -// -Wpadded, -Wpacked
> -def warn_padded_struct_field : Warning<
> -  "padding %select{struct|class}0 %1 with %2 %select{byte|bit}3%select{|s}4 "
> -  "to align %5">, InGroup<Padded>, DefaultIgnore;
> -def warn_padded_struct_anon_field : Warning<
> -  "padding %select{struct|class}0 %1 with %2 %select{byte|bit}3%select{|s}4 "
> -  "to align anonymous bit-field">, InGroup<Padded>, DefaultIgnore;
> -def warn_padded_struct_size : Warning<
> -  "padding size of %0 with %1 %select{byte|bit}2%select{|s}3 "
> -  "to alignment boundary">, InGroup<Padded>, DefaultIgnore;
> +
> +// -Wpadded, -Wpacked
> +def warn_padded_struct_field : Warning<
> +  "padding %select{struct|interface|class}0 %1 with %2 "
> +  "%select{byte|bit}3%select{|s}4 to align %5">,
> +  InGroup<Padded>, DefaultIgnore;
> +def warn_padded_struct_anon_field : Warning<
> +  "padding %select{struct|interface|class}0 %1 with %2 "
> +  "%select{byte|bit}3%select{|s}4 to align anonymous bit-field">,
> +  InGroup<Padded>, DefaultIgnore;
> +def warn_padded_struct_size : Warning<
> +  "padding size of %0 with %1 %select{byte|bit}2%select{|s}3 "
> +  "to alignment boundary">, InGroup<Padded>, DefaultIgnore;
>  def warn_unnecessary_packed : Warning<
>    "packed attribute is unnecessary for %0">, InGroup<Packed>, DefaultIgnore;
>
> @@ -3491,20 +3499,22 @@
>  def ext_flexible_array_in_array : Extension<
>    "%0 may not be used as an array element due to flexible array member">,
>    InGroup<FlexibleArrayExtensions>;
> -def err_flexible_array_init : Error<
> -  "initialization of flexible array member is not allowed">;
> -def ext_flexible_array_empty_aggregate_ms : Extension<
> -  "flexible array member %0 in otherwise empty %select{struct|class}1 "
> -  "is a Microsoft extension">, InGroup<Microsoft>;
> -def ext_flexible_array_union_ms : Extension<
> -  "flexible array member %0 in a union is a Microsoft extension">,
> -  InGroup<Microsoft>;
> -def ext_flexible_array_empty_aggregate_gnu : Extension<
> -  "flexible array member %0 in otherwise empty %select{struct|class}1 "
> -  "is a GNU extension">, InGroup<GNU>;
> -def ext_flexible_array_union_gnu : Extension<
> -  "flexible array member %0 in a union is a GNU extension">, InGroup<GNU>;
> -
> +def err_flexible_array_init : Error<
> +  "initialization of flexible array member is not allowed">;
> +def ext_flexible_array_empty_aggregate_ms : Extension<
> +  "flexible array member %0 in otherwise empty "
> +  "%select{struct|interface|union|class|enum}1 is a Microsoft extension">,
> +  InGroup<Microsoft>;
> +def ext_flexible_array_union_ms : Extension<
> +  "flexible array member %0 in a union is a Microsoft extension">,
> +  InGroup<Microsoft>;
> +def ext_flexible_array_empty_aggregate_gnu : Extension<
> +  "flexible array member %0 in otherwise empty "
> +  "%select{struct|interface|union|class|enum}1 is a GNU extension">,
> +  InGroup<GNU>;
> +def ext_flexible_array_union_gnu : Extension<
> +  "flexible array member %0 in a union is a GNU extension">, InGroup<GNU>;
> +
>  let CategoryName = "ARC Semantic Issue" in {
>
>  // ARC-mode diagnostics.
> @@ -4584,13 +4594,13 @@
>    "because namespace %1 does not enclose namespace %2">;
>  def err_invalid_declarator_global_scope : Error<
>    "definition or redeclaration of %0 cannot name the global scope">;
> -def err_invalid_declarator_in_function : Error<
> -  "definition or redeclaration of %0 not allowed inside a function">;
> -def err_not_tag_in_scope : Error<
> -  "no %select{struct|union|class|enum}0 named %1 in %2">;
> -
> -def err_no_typeid_with_fno_rtti : Error<
> -  "cannot use typeid with -fno-rtti">;
> +def err_invalid_declarator_in_function : Error<
> +  "definition or redeclaration of %0 not allowed inside a function">;
> +def err_not_tag_in_scope : Error<
> +  "no %select{struct|interface|union|class|enum}0 named %1 in %2">;
> +
> +def err_no_typeid_with_fno_rtti : Error<
> +  "cannot use typeid with -fno-rtti">;
>
>  def err_cannot_form_pointer_to_member_of_reference_type : Error<
>    "cannot form a pointer-to-member to member %0 of reference type %1">;
> @@ -5935,13 +5945,13 @@
>    "%select{template|partial|member}0 specialization cannot be "
>    "declared __module_private__">;
>  def err_module_private_local : Error<
> -  "%select{local variable|parameter|typedef}0 %1 cannot be declared "
> -  "__module_private__">;
> -def err_module_private_local_class : Error<
> -  "local %select{struct|union|class|enum}0 cannot be declared "
> -  "__module_private__">;
> -def err_module_private_definition : Error<
> -  "definition of %0 must be imported before it is required">;
> +  "%select{local variable|parameter|typedef}0 %1 cannot be declared "
> +  "__module_private__">;
> +def err_module_private_local_class : Error<
> +  "local %select{struct|interface|union|class|enum}0 cannot be declared "
> +  "__module_private__">;
> +def err_module_private_definition : Error<
> +  "definition of %0 must be imported before it is required">;
>  }
>
>  let CategoryName = "Documentation Issue" in {
>
> Modified: cfe/trunk/include/clang/Basic/Specifiers.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Specifiers.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/Specifiers.h (original)
> +++ cfe/trunk/include/clang/Basic/Specifiers.h Fri Aug 31 13:45:21 2012
> @@ -50,12 +50,13 @@
>      TST_decimal64,    // _Decimal64
>      TST_decimal128,   // _Decimal128
>      TST_enum,
> -    TST_union,
> -    TST_struct,
> -    TST_class,        // C++ class type
> -    TST_typename,     // Typedef, C++ class-name or enum name, etc.
> -    TST_typeofType,
> -    TST_typeofExpr,
> +    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
>
> Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
> +++ cfe/trunk/include/clang/Basic/TokenKinds.def Fri Aug 31 13:45:21 2012
> @@ -505,6 +505,7 @@
>  KEYWORD(__single_inheritance          , KEYMS)
>  KEYWORD(__multiple_inheritance        , KEYMS)
>  KEYWORD(__virtual_inheritance         , KEYMS)
> +KEYWORD(__interface                   , KEYMS)
>  ALIAS("__int8"           , char       , KEYMS)
>  ALIAS("__int16"          , short      , KEYMS)
>  ALIAS("__int32"          , int        , KEYMS)
> @@ -518,7 +519,6 @@
>  ALIAS("_uuidof"          , __uuidof   , KEYMS | KEYBORLAND)
>  ALIAS("_inline"          , inline     , KEYMS)
>  ALIAS("_declspec"        , __declspec , KEYMS)
> -ALIAS("__interface"      , struct     , KEYMS)
>
>  // Borland Extensions which should be disabled in strict conformance mode.
>  ALIAS("_pascal"      , __pascal   , KEYBORLAND)
>
> Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
> +++ cfe/trunk/include/clang/Sema/DeclSpec.h Fri Aug 31 13:45:21 2012
> @@ -266,6 +266,7 @@
>    static const TST TST_enum = clang::TST_enum;
>    static const TST TST_union = clang::TST_union;
>    static const TST TST_struct = clang::TST_struct;
> +  static const TST TST_interface = clang::TST_interface;
>    static const TST TST_class = clang::TST_class;
>    static const TST TST_typename = clang::TST_typename;
>    static const TST TST_typeofType = clang::TST_typeofType;
> @@ -378,7 +379,8 @@
>    }
>    static bool isDeclRep(TST T) {
>      return (T == TST_enum || T == TST_struct ||
> -            T == TST_union || T == TST_class);
> +            T == TST_interface || T == TST_union ||
> +            T == TST_class);
>    }
>
>    DeclSpec(const DeclSpec&);       // DO NOT IMPLEMENT
>
> Modified: cfe/trunk/lib/AST/DeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclCXX.cpp (original)
> +++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Aug 31 13:45:21 2012
> @@ -463,13 +463,14 @@
>  }
>
>  void CXXRecordDecl::addedMember(Decl *D) {
> -  if (!D->isImplicit() &&
> -      !isa<FieldDecl>(D) &&
> -      !isa<IndirectFieldDecl>(D) &&
> -      (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class))
> -    data().HasOnlyCMembers = false;
> -
> -  // Ignore friends and invalid declarations.
> +  if (!D->isImplicit() &&
> +      !isa<FieldDecl>(D) &&
> +      !isa<IndirectFieldDecl>(D) &&
> +      (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class ||
> +        cast<TagDecl>(D)->getTagKind() == TTK_Interface))
> +    data().HasOnlyCMembers = false;
> +
> +  // Ignore friends and invalid declarations.
>    if (D->getFriendObjectKind() || D->isInvalidDecl())
>      return;
>
> @@ -933,13 +934,14 @@
>      if (Shadow->getDeclName().getNameKind()
>            == DeclarationName::CXXConversionFunctionName)
>        data().Conversions.addDecl(Shadow, Shadow->getAccess());
> -}
> -
> -bool CXXRecordDecl::isCLike() const {
> -  if (getTagKind() == TTK_Class || !TemplateOrInstantiation.isNull())
> -    return false;
> -  if (!hasDefinition())
> -    return true;
> +}
> +
> +bool CXXRecordDecl::isCLike() const {
> +  if (getTagKind() == TTK_Class || getTagKind() == TTK_Interface ||
> +      !TemplateOrInstantiation.isNull())
> +    return false;
> +  if (!hasDefinition())
> +    return true;
>
>    return isPOD() && data().HasOnlyCMembers;
>  }
>
> Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
> +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Fri Aug 31 13:45:21 2012
> @@ -1270,12 +1270,13 @@
>  void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
>    switch (T->getDecl()->getTagKind()) {
>      case TTK_Union:
> -      Out << 'T';
> -      break;
> -    case TTK_Struct:
> -      Out << 'U';
> -      break;
> -    case TTK_Class:
> +      Out << 'T';
> +      break;
> +    case TTK_Struct:
> +    case TTK_Interface:
> +      Out << 'U';
> +      break;
> +    case TTK_Class:
>        Out << 'V';
>        break;
>      case TTK_Enum:
>
> Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
> +++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Fri Aug 31 13:45:21 2012
> @@ -2260,12 +2260,28 @@
>    }
>
>    // Use the externally-supplied field offset.
> -  return ExternalFieldOffset;
> -}
> -
> -void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
> -                                            uint64_t UnpaddedOffset,
> -                                            uint64_t UnpackedOffset,
> +  return ExternalFieldOffset;
> +}
> +
> +/// \brief Get diagnostic %select index for tag kind for
> +/// field padding diagnostic message.
> +/// WARNING: Indexes apply to particular diagnostics only!
> +///
> +/// \returns diagnostic %select index.
> +static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)
> +{
> +  switch (Tag) {
> +    case TTK_Struct: return 0;
> +    case TTK_Interface: return 1;
> +    case TTK_Class:  return 2;
> +    default: assert("Invalid tag kind for field padding diagnostic!");
> +  }
> +  return -1;
> +}
> +
> +void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
> +                                            uint64_t UnpaddedOffset,
> +                                            uint64_t UnpackedOffset,
>                                              unsigned UnpackedAlign,
>                                              bool isPacked,
>                                              const FieldDecl *D) {
> @@ -2288,20 +2304,20 @@
>      if (PadSize % CharBitNum == 0) {
>        PadSize = PadSize / CharBitNum;
>        InBits = false;
> -    }
> -    if (D->getIdentifier())
> -      Diag(D->getLocation(), diag::warn_padded_struct_field)
> -          << (D->getParent()->isStruct() ? 0 : 1) // struct|class
> -          << Context.getTypeDeclType(D->getParent())
> -          << PadSize
> -          << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not
> -          << D->getIdentifier();
> -    else
> -      Diag(D->getLocation(), diag::warn_padded_struct_anon_field)
> -          << (D->getParent()->isStruct() ? 0 : 1) // struct|class
> -          << Context.getTypeDeclType(D->getParent())
> -          << PadSize
> -          << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
> +    }
> +    if (D->getIdentifier())
> +      Diag(D->getLocation(), diag::warn_padded_struct_field)
> +          << getPaddingDiagFromTagKind(D->getParent()->getTagKind())
> +          << Context.getTypeDeclType(D->getParent())
> +          << PadSize
> +          << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not
> +          << D->getIdentifier();
> +    else
> +      Diag(D->getLocation(), diag::warn_padded_struct_anon_field)
> +          << getPaddingDiagFromTagKind(D->getParent()->getTagKind())
> +          << Context.getTypeDeclType(D->getParent())
> +          << PadSize
> +          << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
>    }
>
>    // Warn if we packed it unnecessarily. If the alignment is 1 byte don't
>
> Modified: cfe/trunk/lib/AST/Type.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/Type.cpp (original)
> +++ cfe/trunk/lib/AST/Type.cpp Fri Aug 31 13:45:21 2012
> @@ -357,9 +357,15 @@
>      return RT->getDecl()->isStruct();
>    return false;
>  }
> +bool Type::isInterfaceType() const {
> +  if (const RecordType *RT = getAs<RecordType>())
> +    return RT->getDecl()->isInterface();
> +  return false;
> +}
>  bool Type::isStructureOrClassType() const {
>    if (const RecordType *RT = getAs<RecordType>())
> -    return RT->getDecl()->isStruct() || RT->getDecl()->isClass();
> +    return RT->getDecl()->isStruct() || RT->getDecl()->isClass() ||
> +      RT->getDecl()->isInterface();
>    return false;
>  }
>  bool Type::isVoidPointerType() const {
> @@ -1317,6 +1323,7 @@
>    case TST_typename: return ETK_Typename;
>    case TST_class: return ETK_Class;
>    case TST_struct: return ETK_Struct;
> +  case TST_interface: return ETK_Interface;
>    case TST_union: return ETK_Union;
>    case TST_enum: return ETK_Enum;
>    }
> @@ -1327,6 +1334,7 @@
>    switch(TypeSpec) {
>    case TST_class: return TTK_Class;
>    case TST_struct: return TTK_Struct;
> +  case TST_interface: return TTK_Interface;
>    case TST_union: return TTK_Union;
>    case TST_enum: return TTK_Enum;
>    }
> @@ -1339,6 +1347,7 @@
>    switch (Kind) {
>    case TTK_Class: return ETK_Class;
>    case TTK_Struct: return ETK_Struct;
> +  case TTK_Interface: return ETK_Interface;
>    case TTK_Union: return ETK_Union;
>    case TTK_Enum: return ETK_Enum;
>    }
> @@ -1350,6 +1359,7 @@
>    switch (Keyword) {
>    case ETK_Class: return TTK_Class;
>    case ETK_Struct: return TTK_Struct;
> +  case ETK_Interface: return TTK_Interface;
>    case ETK_Union: return TTK_Union;
>    case ETK_Enum: return TTK_Enum;
>    case ETK_None: // Fall through.
> @@ -1367,6 +1377,7 @@
>      return false;
>    case ETK_Class:
>    case ETK_Struct:
> +  case ETK_Interface:
>    case ETK_Union:
>    case ETK_Enum:
>      return true;
> @@ -1381,6 +1392,7 @@
>    case ETK_Typename: return "typename";
>    case ETK_Class:  return "class";
>    case ETK_Struct: return "struct";
> +  case ETK_Interface: return "__interface";
>    case ETK_Union:  return "union";
>    case ETK_Enum:   return "enum";
>    }
>
> Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Fri Aug 31 13:45:21 2012
> @@ -520,13 +520,13 @@
>    const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
>    unsigned Tag = 0;
>    if (CXXDecl) {
> -    RDName = getClassName(RD);
> -    Tag = llvm::dwarf::DW_TAG_class_type;
> -  }
> -  else if (RD->isStruct())
> -    Tag = llvm::dwarf::DW_TAG_structure_type;
> -  else if (RD->isUnion())
> -    Tag = llvm::dwarf::DW_TAG_union_type;
> +    RDName = getClassName(RD);
> +    Tag = llvm::dwarf::DW_TAG_class_type;
> +  }
> +  else if (RD->isStruct() || RD->isInterface())
> +    Tag = llvm::dwarf::DW_TAG_structure_type;
> +  else if (RD->isUnion())
> +    Tag = llvm::dwarf::DW_TAG_union_type;
>    else
>      llvm_unreachable("Unknown RecordDecl type!");
>
>
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Aug 31 13:45:21 2012
> @@ -1875,6 +1875,9 @@
>          TagName="union" ; FixitTagName = "union " ;TagKind=tok::kw_union ;break;
>        case DeclSpec::TST_struct:
>          TagName="struct"; FixitTagName = "struct ";TagKind=tok::kw_struct;break;
> +      case DeclSpec::TST_interface:
> +        TagName="__interface"; FixitTagName = "__interface ";
> +        TagKind=tok::kw___interface;break;
>        case DeclSpec::TST_class:
>          TagName="class" ; FixitTagName = "class " ;TagKind=tok::kw_class ;break;
>      }
> @@ -2709,6 +2712,7 @@
>      // class-specifier:
>      case tok::kw_class:
>      case tok::kw_struct:
> +    case tok::kw___interface:
>      case tok::kw_union: {
>        tok::TokenKind Kind = Tok.getKind();
>        ConsumeToken();
> @@ -3531,6 +3535,7 @@
>      // struct-or-union-specifier (C99) or class-specifier (C++)
>    case tok::kw_class:
>    case tok::kw_struct:
> +  case tok::kw___interface:
>    case tok::kw_union:
>      // enum-specifier
>    case tok::kw_enum:
> @@ -3602,6 +3607,7 @@
>      // struct-or-union-specifier (C99) or class-specifier (C++)
>    case tok::kw_class:
>    case tok::kw_struct:
> +  case tok::kw___interface:
>    case tok::kw_union:
>      // enum-specifier
>    case tok::kw_enum:
> @@ -3740,6 +3746,7 @@
>    case tok::kw_class:
>    case tok::kw_struct:
>    case tok::kw_union:
> +  case tok::kw___interface:
>      // enum-specifier
>    case tok::kw_enum:
>
>
> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Aug 31 13:45:21 2012
> @@ -1031,12 +1031,14 @@
>                                   const ParsedTemplateInfo &TemplateInfo,
>                                   AccessSpecifier AS,
>                                   bool EnteringContext, DeclSpecContext DSC) {
> -  DeclSpec::TST TagType;
> -  if (TagTokKind == tok::kw_struct)
> -    TagType = DeclSpec::TST_struct;
> -  else if (TagTokKind == tok::kw_class)
> -    TagType = DeclSpec::TST_class;
> -  else {
> +  DeclSpec::TST TagType;
> +  if (TagTokKind == tok::kw_struct)
> +    TagType = DeclSpec::TST_struct;
> +  else if (TagTokKind == tok::kw___interface)
> +    TagType = DeclSpec::TST_interface;
> +  else if (TagTokKind == tok::kw_class)
> +    TagType = DeclSpec::TST_class;
> +  else {
>      assert(TagTokKind == tok::kw_union && "Not a class specifier");
>      TagType = DeclSpec::TST_union;
>    }
> @@ -1148,13 +1150,14 @@
>        }
>
>        Diag(NameLoc, diag::err_explicit_spec_non_template)
> -        << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
> -        << (TagType == DeclSpec::TST_class? 0
> -            : TagType == DeclSpec::TST_struct? 1
> -            : 2)
> -        << Name
> -        << SourceRange(LAngleLoc, RAngleLoc);
> -
> +        << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
> +        << (TagType == DeclSpec::TST_class? 0
> +            : TagType == DeclSpec::TST_struct? 1
> +            : TagType == DeclSpec::TST_interface? 2
> +            : 3)
> +        << Name
> +        << SourceRange(LAngleLoc, RAngleLoc);
> +
>        // Strip off the last template parameter list if it was empty, since
>        // we've removed its template argument list.
>        if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
> @@ -1240,14 +1243,13 @@
>               (Tok.is(tok::semi) ||
>                (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) {
>      TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
> -    if (Tok.isNot(tok::semi)) {
> -      // A semicolon was missing after this declaration. Diagnose and recover.
> -      ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
> -                       TagType == DeclSpec::TST_class ? "class" :
> -                       TagType == DeclSpec::TST_struct ? "struct" : "union");
> -      PP.EnterToken(Tok);
> -      Tok.setKind(tok::semi);
> -    }
> +    if (Tok.isNot(tok::semi)) {
> +      // A semicolon was missing after this declaration. Diagnose and recover.
> +      ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
> +        DeclSpec::getSpecifierName(TagType));
> +      PP.EnterToken(Tok);
> +      Tok.setKind(tok::semi);
> +    }
>    } else
>      TUK = Sema::TUK_Reference;
>
> @@ -1466,14 +1468,13 @@
>    // Also enforce C++ [temp]p3:
>    //   In a template-declaration which defines a class, no declarator
>    //   is permitted.
> -  if (TUK == Sema::TUK_Definition &&
> -      (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {
> -    ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
> -                     TagType == DeclSpec::TST_class ? "class" :
> -                     TagType == DeclSpec::TST_struct ? "struct" : "union");
> -    // Push this token back into the preprocessor and change our current token
> -    // to ';' so that the rest of the code recovers as though there were an
> -    // ';' after the definition.
> +  if (TUK == Sema::TUK_Definition &&
> +      (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {
> +    ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
> +      DeclSpec::getSpecifierName(TagType));
> +    // Push this token back into the preprocessor and change our current token
> +    // to ';' so that the rest of the code recovers as though there were an
> +    // ';' after the definition.
>      PP.EnterToken(Tok);
>      Tok.setKind(tok::semi);
>    }
> @@ -2236,12 +2237,13 @@
>  ///         member-declaration member-specification[opt]
>  ///         access-specifier ':' member-specification[opt]
>  ///
> -void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
> -                                         unsigned TagType, Decl *TagDecl) {
> -  assert((TagType == DeclSpec::TST_struct ||
> -         TagType == DeclSpec::TST_union  ||
> -         TagType == DeclSpec::TST_class) && "Invalid TagType!");
> -
> +void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
> +                                         unsigned TagType, Decl *TagDecl) {
> +  assert((TagType == DeclSpec::TST_struct ||
> +         TagType == DeclSpec::TST_interface ||
> +         TagType == DeclSpec::TST_union  ||
> +         TagType == DeclSpec::TST_class) && "Invalid TagType!");
> +
>    PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
>                                        "parsing struct/union/class body");
>
>
> Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
> +++ cfe/trunk/lib/Sema/DeclSpec.cpp Fri Aug 31 13:45:21 2012
> @@ -270,6 +270,7 @@
>      case TST_int:
>      case TST_int128:
>      case TST_struct:
> +    case TST_interface:
>      case TST_union:
>      case TST_unknown_anytype:
>      case TST_unspecified:
> @@ -400,6 +401,7 @@
>    case DeclSpec::TST_class:       return "class";
>    case DeclSpec::TST_union:       return "union";
>    case DeclSpec::TST_struct:      return "struct";
> +  case DeclSpec::TST_interface:   return "__interface";
>    case DeclSpec::TST_typename:    return "type-name";
>    case DeclSpec::TST_typeofType:
>    case DeclSpec::TST_typeofExpr:  return "typeof";
>
> Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Fri Aug 31 13:45:21 2012
> @@ -1059,10 +1059,12 @@
>    // Allow us to find class templates, too.
>    if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
>      ND = ClassTemplate->getTemplatedDecl();
> -
> +
> +  // For purposes of this check, interfaces match too.
>    if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
>      return RD->getTagKind() == TTK_Class ||
> -    RD->getTagKind() == TTK_Struct;
> +    RD->getTagKind() == TTK_Struct ||
> +    RD->getTagKind() == TTK_Interface;
>
>    return false;
>  }
> @@ -1422,7 +1424,8 @@
>          if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
>            switch (Tag->getTagKind()) {
>            case TTK_Struct: return "struct <anonymous>";
> -          case TTK_Class:  return "class <anonymous>";
> +          case TTK_Interface: return "__interface <anonymous>";
> +          case TTK_Class:  return "class <anonymous>";
>            case TTK_Union:  return "union <anonymous>";
>            case TTK_Enum:   return "enum <anonymous>";
>            }
> @@ -1449,7 +1452,7 @@
>                                                       Policy,
>                                                       Allocator));
>    Builder.AddTypedTextChunk("this");
> -  Results.AddResult(CodeCompletionResult(Builder.TakeString()));
> +  Results.AddResult(CodeCompletionResult(Builder.TakeString()));
>  }
>
>  /// \brief Add language constructs that show up for "ordinary" names.
> @@ -2884,6 +2887,7 @@
>      default:
>        if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
>          switch (TD->getTagKind()) {
> +          case TTK_Interface:  // fall through
>            case TTK_Struct: return CXCursor_StructDecl;
>            case TTK_Class:  return CXCursor_ClassDecl;
>            case TTK_Union:  return CXCursor_UnionDecl;
> @@ -3601,6 +3605,7 @@
>
>    case DeclSpec::TST_struct:
>    case DeclSpec::TST_class:
> +  case DeclSpec::TST_interface:
>      Filter = &ResultBuilder::IsClassOrStruct;
>      ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
>      break;
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Aug 31 13:45:21 2012
> @@ -350,8 +350,8 @@
>  /// isTagName() - This method is called *for error recovery purposes only*
>  /// to determine if the specified name is a valid tag name ("struct foo").  If
>  /// so, this returns the TST for the tag corresponding to it (TST_enum,
> -/// TST_union, TST_struct, TST_class).  This is used to diagnose cases in C
> -/// where the user forgot to specify the tag.
> +/// TST_union, TST_struct, TST_interface, TST_class).  This is used to diagnose
> +/// cases in C where the user forgot to specify the tag.
>  DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
>    // Do a tag name lookup in this scope.
>    LookupResult R(*this, &II, SourceLocation(), LookupTagName);
> @@ -361,6 +361,7 @@
>      if (const TagDecl *TD = R.getAsSingle<TagDecl>()) {
>        switch (TD->getTagKind()) {
>        case TTK_Struct: return DeclSpec::TST_struct;
> +      case TTK_Interface: return DeclSpec::TST_interface;
>        case TTK_Union:  return DeclSpec::TST_union;
>        case TTK_Class:  return DeclSpec::TST_class;
>        case TTK_Enum:   return DeclSpec::TST_enum;
> @@ -538,6 +539,11 @@
>          FixItTagName = "struct ";
>          break;
>
> +      case TTK_Interface:
> +        TagName = "__interface";
> +        FixItTagName = "__interface ";
> +        break;
> +
>        case TTK_Union:
>          TagName = "union";
>          FixItTagName = "union ";
> @@ -2604,6 +2610,7 @@
>    TagDecl *Tag = 0;
>    if (DS.getTypeSpecType() == DeclSpec::TST_class ||
>        DS.getTypeSpecType() == DeclSpec::TST_struct ||
> +      DS.getTypeSpecType() == DeclSpec::TST_interface ||
>        DS.getTypeSpecType() == DeclSpec::TST_union ||
>        DS.getTypeSpecType() == DeclSpec::TST_enum) {
>      TagD = DS.getRepAsDecl();
> @@ -2642,7 +2649,8 @@
>        Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag)
>          << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 :
>              DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 :
> -            DS.getTypeSpecType() == DeclSpec::TST_union ? 2 : 3);
> +            DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 :
> +            DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4);
>      else
>        Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators);
>      // Don't emit warnings after this error.
> @@ -2763,6 +2771,7 @@
>      DeclSpec::TST TypeSpecType = DS.getTypeSpecType();
>      if (TypeSpecType == DeclSpec::TST_class ||
>          TypeSpecType == DeclSpec::TST_struct ||
> +        TypeSpecType == DeclSpec::TST_interface ||
>          TypeSpecType == DeclSpec::TST_union ||
>          TypeSpecType == DeclSpec::TST_enum) {
>        AttributeList* attrs = DS.getAttributes().getList();
> @@ -2772,7 +2781,8 @@
>          << attrs->getName()
>          << (TypeSpecType == DeclSpec::TST_class ? 0 :
>              TypeSpecType == DeclSpec::TST_struct ? 1 :
> -            TypeSpecType == DeclSpec::TST_union ? 2 : 3);
> +            TypeSpecType == DeclSpec::TST_union ? 2 :
> +            TypeSpecType == DeclSpec::TST_interface ? 3 : 4);
>          attrs = attrs->getNext();
>        }
>      }
> @@ -5185,6 +5195,14 @@
>        NewFD->setImplicitlyInline();
>      }
>
> +    // if this is a method defined in an __interface, set pure
> +    // (isVirtual will already return true)
> +    if (CXXRecordDecl *Parent = dyn_cast<CXXRecordDecl>(
> +        NewFD->getDeclContext())) {
> +      if (Parent->getTagKind() == TTK_Interface)
> +        NewFD->setPure(true);
> +    }
> +
>      SetNestedNameSpecifier(NewFD, D);
>      isExplicitSpecialization = false;
>      isFunctionTemplateSpecialization = false;
> @@ -8118,6 +8136,7 @@
>    switch (D.getDeclSpec().getTypeSpecType()) {
>    case TST_enum:
>    case TST_struct:
> +  case TST_interface:
>    case TST_union:
>    case TST_class: {
>      TagDecl *tagFromDeclSpec = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
> @@ -8193,6 +8212,31 @@
>    return false;
>  }
>
> +/// \brief Get diagnostic %select index for tag kind for
> +/// redeclaration diagnostic message.
> +/// WARNING: Indexes apply to particular diagnostics only!
> +///
> +/// \returns diagnostic %select index.
> +static unsigned getRedeclDiagFromTagKind(TagTypeKind Tag)
> +{
> +  switch (Tag) {
> +    case TTK_Struct: return 0;
> +    case TTK_Interface: return 1;
> +    case TTK_Class:  return 2;
> +    default: assert("Invalid tag kind for redecl diagnostic!");
> +  }
> +  return -1;
> +}
> +
> +/// \brief Determine if tag kind is a class-key compatible with
> +/// class for redeclaration (class, struct, or __interface).
> +///
> +/// \returns true iff the tag kind is compatible.
> +static bool isClassCompatTagKind(TagTypeKind Tag)
> +{
> +  return Tag == TTK_Struct || Tag == TTK_Class || Tag == TTK_Interface;
> +}
> +
>  /// \brief Determine whether a tag with a given kind is acceptable
>  /// as a redeclaration of the given tag declaration.
>  ///
> @@ -8215,12 +8259,11 @@
>    //   struct class-key shall be used to refer to a class (clause 9)
>    //   declared using the class or struct class-key.
>    TagTypeKind OldTag = Previous->getTagKind();
> -  if (!isDefinition || (NewTag != TTK_Class && NewTag != TTK_Struct))
> +  if (!isDefinition || !isClassCompatTagKind(NewTag))
>      if (OldTag == NewTag)
>        return true;
>
> -  if ((OldTag == TTK_Struct || OldTag == TTK_Class) &&
> -      (NewTag == TTK_Struct || NewTag == TTK_Class)) {
> +  if (isClassCompatTagKind(OldTag) && isClassCompatTagKind(NewTag)) {
>      // Warn about the struct/class tag mismatch.
>      bool isTemplate = false;
>      if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous))
> @@ -8230,7 +8273,8 @@
>        // In a template instantiation, do not offer fix-its for tag mismatches
>        // since they usually mess up the template instead of fixing the problem.
>        Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
> -        << (NewTag == TTK_Class) << isTemplate << &Name;
> +        << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
> +        << getRedeclDiagFromTagKind(OldTag);
>        return true;
>      }
>
> @@ -8249,13 +8293,13 @@
>            if (!previousMismatch) {
>              previousMismatch = true;
>              Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch)
> -              << (NewTag == TTK_Class) << isTemplate << &Name;
> +              << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
> +              << getRedeclDiagFromTagKind(I->getTagKind());
>            }
>            Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion)
> -            << (NewTag == TTK_Class)
> +            << getRedeclDiagFromTagKind(NewTag)
>              << FixItHint::CreateReplacement(I->getInnerLocStart(),
> -                                            NewTag == TTK_Class?
> -                                            "class" : "struct");
> +                 TypeWithKeyword::getTagTypeKindName(NewTag));
>          }
>        }
>        return true;
> @@ -8271,16 +8315,16 @@
>      }
>
>      Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
> -      << (NewTag == TTK_Class)
> -      << isTemplate << &Name;
> +      << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
> +      << getRedeclDiagFromTagKind(OldTag);
>      Diag(Redecl->getLocation(), diag::note_previous_use);
>
>      // If there is a previous defintion, suggest a fix-it.
>      if (Previous->getDefinition()) {
>          Diag(NewTagLoc, diag::note_struct_class_suggestion)
> -          << (Redecl->getTagKind() == TTK_Class)
> +          << getRedeclDiagFromTagKind(Redecl->getTagKind())
>            << FixItHint::CreateReplacement(SourceRange(NewTagLoc),
> -                        Redecl->getTagKind() == TTK_Class? "class" : "struct");
> +               TypeWithKeyword::getTagTypeKindName(Redecl->getTagKind()));
>      }
>
>      return true;
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Aug 31 13:45:21 2012
> @@ -672,12 +672,28 @@
>                                     isa<CXXConstructorDecl>(FD)))
>        return false;
>    }
> -  return true;
> -}
> -
> -// CheckConstexprFunctionDecl - Check whether a function declaration satisfies
> -// the requirements of a constexpr function definition or a constexpr
> -// constructor definition. If so, return true. If not, produce appropriate
> +  return true;
> +}
> +
> +/// \brief Get diagnostic %select index for tag kind for
> +/// record diagnostic message.
> +/// WARNING: Indexes apply to particular diagnostics only!
> +///
> +/// \returns diagnostic %select index.
> +static unsigned getRecordDiagFromTagKind(TagTypeKind Tag)
> +{
> +  switch (Tag) {
> +    case TTK_Struct: return 0;
> +    case TTK_Interface: return 1;
> +    case TTK_Class:  return 2;
> +    default: assert("Invalid tag kind for record diagnostic!");
> +  }
> +  return -1;
> +}
> +
> +// CheckConstexprFunctionDecl - Check whether a function declaration satisfies
> +// the requirements of a constexpr function definition or a constexpr
> +// constructor definition. If so, return true. If not, produce appropriate
>  // diagnostics and return false.
>  //
>  // This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360.
> @@ -688,14 +704,14 @@
>      //  The definition of a constexpr constructor shall satisfy the following
>      //  constraints:
>      //  - the class shall not have any virtual base classes;
> -    const CXXRecordDecl *RD = MD->getParent();
> -    if (RD->getNumVBases()) {
> -      Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base)
> -        << isa<CXXConstructorDecl>(NewFD) << RD->isStruct()
> -        << RD->getNumVBases();
> -      for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
> -             E = RD->vbases_end(); I != E; ++I)
> -        Diag(I->getLocStart(),
> +    const CXXRecordDecl *RD = MD->getParent();
> +    if (RD->getNumVBases()) {
> +      Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base)
> +        << isa<CXXConstructorDecl>(NewFD)
> +        << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
> +      for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
> +             E = RD->vbases_end(); I != E; ++I)
> +        Diag(I->getLocStart(),
>               diag::note_constexpr_virtual_base_here) << I->getSourceRange();
>        return false;
>      }
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Aug 31 13:45:21 2012
> @@ -2998,7 +2998,7 @@
>    case UTT_IsUnion:
>      return T->isUnionType();
>    case UTT_IsClass:
> -    return T->isClassType() || T->isStructureType();
> +    return T->isClassType() || T->isStructureType() || T->isInterfaceType();
>    case UTT_IsFunction:
>      return T->isFunctionType();
>
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Fri Aug 31 13:45:21 2012
> @@ -727,6 +727,7 @@
>    case TST_enum:
>    case TST_union:
>    case TST_struct:
> +  case TST_interface:
>    case TST_class:
>    case TST_auto:
>    case TST_unknown_anytype:
>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Fri Aug 31 13:45:21 2012
> @@ -753,7 +753,8 @@
>    case DeclSpec::TST_class:
>    case DeclSpec::TST_enum:
>    case DeclSpec::TST_union:
> -  case DeclSpec::TST_struct: {
> +  case DeclSpec::TST_struct:
> +  case DeclSpec::TST_interface: {
>      TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl());
>      if (!D) {
>        // This can happen in C++ with ambiguous lookups.
> @@ -1853,30 +1854,31 @@
>        case TTK_Struct: Error = 1; /* Struct member */ break;
>        case TTK_Union:  Error = 2; /* Union member */ break;
>        case TTK_Class:  Error = 3; /* Class member */ break;
> +      case TTK_Interface: Error = 4; /* Interface member */ break;
>        }
>        break;
>      case Declarator::CXXCatchContext:
>      case Declarator::ObjCCatchContext:
> -      Error = 4; // Exception declaration
> +      Error = 5; // Exception declaration
>        break;
>      case Declarator::TemplateParamContext:
> -      Error = 5; // Template parameter
> +      Error = 6; // Template parameter
>        break;
>      case Declarator::BlockLiteralContext:
> -      Error = 6; // Block literal
> +      Error = 7; // Block literal
>        break;
>      case Declarator::TemplateTypeArgContext:
> -      Error = 7; // Template type argument
> +      Error = 8; // Template type argument
>        break;
>      case Declarator::AliasDeclContext:
>      case Declarator::AliasTemplateContext:
> -      Error = 9; // Type alias
> +      Error = 10; // Type alias
>        break;
>      case Declarator::TrailingReturnContext:
> -      Error = 10; // Function return type
> +      Error = 11; // Function return type
>        break;
>      case Declarator::TypeNameContext:
> -      Error = 11; // Generic
> +      Error = 12; // Generic
>        break;
>      case Declarator::FileContext:
>      case Declarator::BlockContext:
> @@ -1887,11 +1889,11 @@
>      }
>
>      if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
> -      Error = 8;
> +      Error = 9;
>
>      // In Objective-C it is an error to use 'auto' on a function declarator.
>      if (D.isFunctionDeclarator())
> -      Error = 10;
> +      Error = 11;
>
>      // C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator
>      // contains a trailing return type. That is only legal at the outermost
> @@ -4430,6 +4432,22 @@
>    return RequireCompleteType(Loc, T, Diagnoser);
>  }
>
> +/// \brief Get diagnostic %select index for tag kind for
> +/// literal type diagnostic message.
> +/// WARNING: Indexes apply to particular diagnostics only!
> +///
> +/// \returns diagnostic %select index.
> +static unsigned getLiteralDiagFromTagKind(TagTypeKind Tag)
> +{
> +  switch (Tag) {
> +    case TTK_Struct: return 0;
> +    case TTK_Interface: return 1;
> +    case TTK_Class:  return 2;
> +    default: assert("Invalid tag kind for literal type diagnostic!");
> +  }
> +  return -1;
> +}
> +
>  /// @brief Ensure that the type T is a literal type.
>  ///
>  /// This routine checks whether the type @p T is a literal type. If @p T is an
> @@ -4486,7 +4504,7 @@
>    // of constexpr constructors.
>    if (RD->getNumVBases()) {
>      Diag(RD->getLocation(), diag::note_non_literal_virtual_base)
> -      << RD->isStruct() << RD->getNumVBases();
> +      << getLiteralDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
>      for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
>             E = RD->vbases_end(); I != E; ++I)
>        Diag(I->getLocStart(),
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Aug 31 13:45:21 2012
> @@ -1716,14 +1716,16 @@
>      return true;
>
>    // Compatible tags match.
> -  if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {
> -    TagDecl *TagY = cast<TagDecl>(Y);
> -    return (TagX->getTagKind() == TagY->getTagKind()) ||
> -      ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class) &&
> -       (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class));
> -  }
> -
> -  // Functions with the same type and linkage match.
> +  if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {
> +    TagDecl *TagY = cast<TagDecl>(Y);
> +    return (TagX->getTagKind() == TagY->getTagKind()) ||
> +      ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class ||
> +        TagX->getTagKind() == TTK_Interface) &&
> +       (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class ||
> +        TagY->getTagKind() == TTK_Interface));
> +  }
> +
> +  // Functions with the same type and linkage match.
>    // FIXME: This needs to cope with function templates, merging of
>    //prototyped/non-prototyped functions, etc.
>    if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) {
>
> Modified: cfe/trunk/test/Parser/MicrosoftExtensions.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/test/Parser/MicrosoftExtensions.cpp (original)
> +++ cfe/trunk/test/Parser/MicrosoftExtensions.cpp Fri Aug 31 13:45:21 2012
> @@ -171,19 +171,27 @@
>     int k = typename var;// expected-error {{expected a qualified name after 'typename'}}
>  }
>
> -
> -__interface MicrosoftInterface;
> -__interface MicrosoftInterface {
> -   virtual void foo1() = 0;
> -   virtual void foo2() = 0;
> -};
> -
> -void interface_test() {
> -  MicrosoftInterface* a;
> -  a->foo1();
> -}
> -
> -__int64 x7 = __int64(0);
> +
> +__interface MicrosoftInterface;
> +__interface MicrosoftInterface {
> +   void foo1() = 0;
> +   virtual void foo2() = 0;
> +};
> +
> +__interface MicrosoftDerivedInterface : public MicrosoftInterface {
> +  void foo1();
> +  void foo2() override;
> +  void foo3();
> +};
> +
> +void interface_test() {
> +  MicrosoftInterface* a;
> +  a->foo1();
> +  MicrosoftDerivedInterface* b;
> +  b->foo2();
> +}
> +
> +__int64 x7 = __int64(0);
>
>
>  namespace If_exists_test {
>
> Modified: cfe/trunk/tools/libclang/CIndexCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexCXX.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/tools/libclang/CIndexCXX.cpp (original)
> +++ cfe/trunk/tools/libclang/CIndexCXX.cpp Fri Aug 31 13:45:21 2012
> @@ -64,14 +64,15 @@
>
>    case CXCursor_ClassTemplatePartialSpecialization:
>      if (ClassTemplateSpecializationDecl *PartialSpec
> -          = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
> -                                                            getCursorDecl(C))) {
> -      switch (PartialSpec->getTagKind()) {
> -      case TTK_Class: return CXCursor_ClassDecl;
> -      case TTK_Struct: return CXCursor_StructDecl;
> -      case TTK_Union: return CXCursor_UnionDecl;
> -      case TTK_Enum: return CXCursor_NoDeclFound;
> -      }
> +          = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
> +                                                            getCursorDecl(C))) {
> +      switch (PartialSpec->getTagKind()) {
> +      case TTK_Interface:
> +      case TTK_Struct: return CXCursor_StructDecl;
> +      case TTK_Class: return CXCursor_ClassDecl;
> +      case TTK_Union: return CXCursor_UnionDecl;
> +      case TTK_Enum: return CXCursor_NoDeclFound;
> +      }
>      }
>      break;
>
>
> Modified: cfe/trunk/tools/libclang/CIndexUSRs.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexUSRs.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/tools/libclang/CIndexUSRs.cpp (original)
> +++ cfe/trunk/tools/libclang/CIndexUSRs.cpp Fri Aug 31 13:45:21 2012
> @@ -1,932 +1,935 @@
> -//===- 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 bool InAnonymousNamespace(const Decl *D) {
> -  if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D->getDeclContext()))
> -    return ND->isAnonymousNamespace();
> -  return false;
> -}
> -
> -static inline bool ShouldGenerateLocation(const NamedDecl *D) {
> -  return D->getLinkage() != ExternalLinkage && !InAnonymousNamespace(D);
> -}
> -
> -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_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_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_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:
> -    if (Decl *D = Arg.getAsDecl())
> -      Visit(D);
> -    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;
> -
> -  // Check if the cursor has 'NoLinkage'.
> -  if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
> -    switch (ND->getLinkage()) {
> -      case ExternalLinkage:
> -        // Generate USRs for all entities with external linkage.
> -        break;
> -      case NoLinkage:
> -      case UniqueExternalLinkage:
> -        // We allow enums, typedefs, and structs that have no linkage to
> -        // have USRs that are anchored to the file they were defined in
> -        // (e.g., the header).  This is a little gross, but in principal
> -        // enums/anonymous structs/etc. defined in a common header file
> -        // are referred to across multiple translation units.
> -        if (isa<TagDecl>(ND) || isa<TypedefDecl>(ND) ||
> -            isa<EnumConstantDecl>(ND) || isa<FieldDecl>(ND) ||
> -            isa<VarDecl>(ND) || isa<NamespaceDecl>(ND))
> -          break;
> -        // Fall-through.
> -      case InternalLinkage:
> -        if (isa<FunctionDecl>(ND))
> -          break;
> -    }
> -
> -  {
> -    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"
> +//===- 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 bool InAnonymousNamespace(const Decl *D) {
> +  if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D->getDeclContext()))
> +    return ND->isAnonymousNamespace();
> +  return false;
> +}
> +
> +static inline bool ShouldGenerateLocation(const NamedDecl *D) {
> +  return D->getLinkage() != ExternalLinkage && !InAnonymousNamespace(D);
> +}
> +
> +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:
> +    if (Decl *D = Arg.getAsDecl())
> +      Visit(D);
> +    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;
> +
> +  // Check if the cursor has 'NoLinkage'.
> +  if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
> +    switch (ND->getLinkage()) {
> +      case ExternalLinkage:
> +        // Generate USRs for all entities with external linkage.
> +        break;
> +      case NoLinkage:
> +      case UniqueExternalLinkage:
> +        // We allow enums, typedefs, and structs that have no linkage to
> +        // have USRs that are anchored to the file they were defined in
> +        // (e.g., the header).  This is a little gross, but in principal
> +        // enums/anonymous structs/etc. defined in a common header file
> +        // are referred to across multiple translation units.
> +        if (isa<TagDecl>(ND) || isa<TypedefDecl>(ND) ||
> +            isa<EnumConstantDecl>(ND) || isa<FieldDecl>(ND) ||
> +            isa<VarDecl>(ND) || isa<NamespaceDecl>(ND))
> +          break;
> +        // Fall-through.
> +      case InternalLinkage:
> +        if (isa<FunctionDecl>(ND))
> +          break;
> +    }
> +
> +  {
> +    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"
>
> Modified: cfe/trunk/tools/libclang/IndexingContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexingContext.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/tools/libclang/IndexingContext.cpp (original)
> +++ cfe/trunk/tools/libclang/IndexingContext.cpp Fri Aug 31 13:45:21 2012
> @@ -852,12 +852,16 @@
>      case TTK_Union:
>        EntityInfo.kind = CXIdxEntity_Union; break;
>      case TTK_Class:
> -      EntityInfo.kind = CXIdxEntity_CXXClass;
> -      EntityInfo.lang = CXIdxEntityLang_CXX;
> -      break;
> -    case TTK_Enum:
> -      EntityInfo.kind = CXIdxEntity_Enum; break;
> -    }
> +      EntityInfo.kind = CXIdxEntity_CXXClass;
> +      EntityInfo.lang = CXIdxEntityLang_CXX;
> +      break;
> +    case TTK_Interface:
> +      EntityInfo.kind = CXIdxEntity_CXXInterface;
> +      EntityInfo.lang = CXIdxEntityLang_CXX;
> +      break;
> +    case TTK_Enum:
> +      EntityInfo.kind = CXIdxEntity_Enum; break;
> +    }
>
>      if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D))
>        if (!CXXRec->isCLike())
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list