[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/

Joao Matos ripzonetriton at gmail.com
Fri Aug 31 11:45:22 PDT 2012


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
+
+} 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())





More information about the cfe-commits mailing list