[cfe-commits] r163013 - in /cfe/trunk: include/clang-c/ include/clang/AST/ include/clang/Basic/ include/clang/Sema/ lib/AST/ lib/CodeGen/ lib/Parse/ lib/Sema/ lib/Serialization/ test/Parser/ tools/libclang/
David Blaikie
dblaikie at gmail.com
Fri Aug 31 14:57:42 PDT 2012
On Fri, Aug 31, 2012 at 11:45 AM, Joao Matos <ripzonetriton at gmail.com> wrote:
> Author: triton
> Date: Fri Aug 31 13:45:21 2012
> New Revision: 163013
>
> URL: http://llvm.org/viewvc/llvm-project?rev=163013&view=rev
> Log:
> Improved MSVC __interface support by adding first class support for it, instead of aliasing to "struct" which had some incorrect behaviour. Patch by David Robins.
>
> Modified:
> cfe/trunk/include/clang-c/Index.h
> cfe/trunk/include/clang/AST/CanonicalType.h
> cfe/trunk/include/clang/AST/Decl.h
> cfe/trunk/include/clang/AST/DeclCXX.h
> cfe/trunk/include/clang/AST/Type.h
> cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
> cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/include/clang/Basic/Specifiers.h
> cfe/trunk/include/clang/Basic/TokenKinds.def
> cfe/trunk/include/clang/Sema/DeclSpec.h
> cfe/trunk/lib/AST/DeclCXX.cpp
> cfe/trunk/lib/AST/MicrosoftMangle.cpp
> cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
> cfe/trunk/lib/AST/Type.cpp
> cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
> cfe/trunk/lib/Parse/ParseDecl.cpp
> cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> cfe/trunk/lib/Sema/DeclSpec.cpp
> cfe/trunk/lib/Sema/SemaCodeComplete.cpp
> cfe/trunk/lib/Sema/SemaDecl.cpp
> cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> cfe/trunk/lib/Sema/SemaExprCXX.cpp
> cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
> cfe/trunk/lib/Sema/SemaType.cpp
> cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> cfe/trunk/test/Parser/MicrosoftExtensions.cpp
> cfe/trunk/tools/libclang/CIndexCXX.cpp
> cfe/trunk/tools/libclang/CIndexUSRs.cpp
> cfe/trunk/tools/libclang/IndexingContext.cpp
>
> Modified: cfe/trunk/include/clang-c/Index.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang-c/Index.h (original)
> +++ cfe/trunk/include/clang-c/Index.h Fri Aug 31 13:45:21 2012
> @@ -4962,13 +4962,14 @@
> CXIdxEntity_CXXStaticVariable = 19,
> CXIdxEntity_CXXStaticMethod = 20,
> CXIdxEntity_CXXInstanceMethod = 21,
> - CXIdxEntity_CXXConstructor = 22,
> - CXIdxEntity_CXXDestructor = 23,
> - CXIdxEntity_CXXConversionFunction = 24,
> - CXIdxEntity_CXXTypeAlias = 25
> -
> -} CXIdxEntityKind;
> -
> + CXIdxEntity_CXXConstructor = 22,
> + CXIdxEntity_CXXDestructor = 23,
> + CXIdxEntity_CXXConversionFunction = 24,
> + CXIdxEntity_CXXTypeAlias = 25,
> + CXIdxEntity_CXXInterface = 26
This caused a build break/warning:
/home/blaikie/local/Development/llvm/src/tools/clang/tools/c-index-test/c-index-test.c:2183:11:
error: enumeration value 'CXIdxEntity_CXXInterface' not handled in
switch [-Werror,-Wswitch]
switch (kind) {
^
I've fixed this in r163025.
> +
> +} CXIdxEntityKind;
> +
> typedef enum {
> CXIdxEntityLang_None = 0,
> CXIdxEntityLang_C = 1,
>
> Modified: cfe/trunk/include/clang/AST/CanonicalType.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CanonicalType.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/CanonicalType.h (original)
> +++ cfe/trunk/include/clang/AST/CanonicalType.h Fri Aug 31 13:45:21 2012
> @@ -276,6 +276,7 @@
> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType)
> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType)
> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType)
> + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isInterfaceType)
> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType)
> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType)
> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType)
>
> Modified: cfe/trunk/include/clang/AST/Decl.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Decl.h (original)
> +++ cfe/trunk/include/clang/AST/Decl.h Fri Aug 31 13:45:21 2012
> @@ -2448,7 +2448,7 @@
> private:
> // FIXME: This can be packed into the bitfields in Decl.
> /// TagDeclKind - The TagKind enum.
> - unsigned TagDeclKind : 2;
> + unsigned TagDeclKind : 3;
>
> /// IsCompleteDefinition - True if this is a definition ("struct foo
> /// {};"), false if it is a declaration ("struct foo;"). It is not
> @@ -2625,6 +2625,7 @@
> void setTagKind(TagKind TK) { TagDeclKind = TK; }
>
> bool isStruct() const { return getTagKind() == TTK_Struct; }
> + bool isInterface() const { return getTagKind() == TTK_Interface; }
> bool isClass() const { return getTagKind() == TTK_Class; }
> bool isUnion() const { return getTagKind() == TTK_Union; }
> bool isEnum() const { return getTagKind() == TTK_Enum; }
>
> Modified: cfe/trunk/include/clang/AST/DeclCXX.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/DeclCXX.h (original)
> +++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Aug 31 13:45:21 2012
> @@ -1553,13 +1553,15 @@
> bool isVolatile() { return getType()->castAs<FunctionType>()->isVolatile(); }
>
> bool isVirtual() const {
> - CXXMethodDecl *CD =
> - cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl());
> -
> - if (CD->isVirtualAsWritten())
> - return true;
> -
> - return (CD->begin_overridden_methods() != CD->end_overridden_methods());
> + CXXMethodDecl *CD =
> + cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl());
> +
> + // Methods declared in interfaces are automatically (pure) virtual
> + if (CD->isVirtualAsWritten() ||
> + CD->getParent()->getTagKind() == TTK_Interface)
> + return true;
> +
> + return (CD->begin_overridden_methods() != CD->end_overridden_methods());
> }
>
> /// \brief Determine whether this is a usual deallocation function
>
> Modified: cfe/trunk/include/clang/AST/Type.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Type.h (original)
> +++ cfe/trunk/include/clang/AST/Type.h Fri Aug 31 13:45:21 2012
> @@ -1512,6 +1512,7 @@
> bool isRecordType() const;
> bool isClassType() const;
> bool isStructureType() const;
> + bool isInterfaceType() const;
> bool isStructureOrClassType() const;
> bool isUnionType() const;
> bool isComplexIntegerType() const; // GCC _Complex integer type.
> @@ -3796,6 +3797,8 @@
> enum TagTypeKind {
> /// \brief The "struct" keyword.
> TTK_Struct,
> + /// \brief The "__interface" keyword.
> + TTK_Interface,
> /// \brief The "union" keyword.
> TTK_Union,
> /// \brief The "class" keyword.
> @@ -3809,6 +3812,8 @@
> enum ElaboratedTypeKeyword {
> /// \brief The "struct" keyword introduces the elaborated-type-specifier.
> ETK_Struct,
> + /// \brief The "__interface" keyword introduces the elaborated-type-specifier.
> + ETK_Interface,
> /// \brief The "union" keyword introduces the elaborated-type-specifier.
> ETK_Union,
> /// \brief The "class" keyword introduces the elaborated-type-specifier.
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Fri Aug 31 13:45:21 2012
> @@ -134,13 +134,13 @@
> def err_odr_function_type_inconsistent : Error<
> "external function %0 declared with incompatible types in different "
> "translation units (%1 vs. %2)">;
> -def warn_odr_tag_type_inconsistent : Warning<
> - "type %0 has incompatible definitions in different translation units">;
> -def note_odr_tag_kind_here: Note<
> - "%0 is a %select{struct|union|class|enum}1 here">;
> -def note_odr_field : Note<"field %0 has type %1 here">;
> -def note_odr_missing_field : Note<"no corresponding field here">;
> -def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">;
> +def warn_odr_tag_type_inconsistent : Warning<
> + "type %0 has incompatible definitions in different translation units">;
> +def note_odr_tag_kind_here: Note<
> + "%0 is a %select{struct|interface|union|class|enum}1 here">;
> +def note_odr_field : Note<"field %0 has type %1 here">;
> +def note_odr_missing_field : Note<"no corresponding field here">;
> +def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">;
> def note_odr_not_bit_field : Note<"field %0 is not a bit-field">;
> def note_odr_base : Note<"class has base type %0">;
> def note_odr_virtual_base : Note<
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Fri Aug 31 13:45:21 2012
> @@ -573,13 +573,13 @@
> def err_typename_refers_to_non_type_template : Error<
> "typename specifier refers to a non-template">;
> def err_expected_type_name_after_typename : Error<
> - "expected an identifier or template-id after '::'">;
> -def err_explicit_spec_non_template : Error<
> - "explicit %select{specialization|instantiation}0 of non-template "
> - "%select{class|struct|union}1 %2">;
> -
> -def err_default_template_template_parameter_not_template : Error<
> - "default template argument for a template template parameter must be a class "
> + "expected an identifier or template-id after '::'">;
> +def err_explicit_spec_non_template : Error<
> + "explicit %select{specialization|instantiation}0 of non-template "
> + "%select{class|struct|union|interface}1 %2">;
> +
> +def err_default_template_template_parameter_not_template : Error<
> + "default template argument for a template template parameter must be a class "
> "template">;
>
> def err_ctor_init_missing_comma : Error<
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Aug 31 13:45:21 2012
> @@ -793,16 +793,17 @@
> "friends cannot be members of the declaring class">;
> def warn_cxx98_compat_friend_is_member : Warning<
> "friend declaration naming a member of the declaring class is incompatible "
> - "with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
> -def ext_unelaborated_friend_type : ExtWarn<
> - "unelaborated friend declaration is a C++11 extension; specify "
> - "'%select{struct|union|class|enum}0' to befriend %1">, InGroup<CXX11>;
> -def warn_cxx98_compat_unelaborated_friend_type : Warning<
> - "befriending %1 without '%select{struct|union|class|enum}0' keyword is "
> - "incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
> -def err_qualified_friend_not_found : Error<
> - "no function named %0 with type %1 was found in the specified scope">;
> -def err_introducing_special_friend : Error<
> + "with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
> +def ext_unelaborated_friend_type : ExtWarn<
> + "unelaborated friend declaration is a C++11 extension; specify "
> + "'%select{struct|interface|union|class|enum}0' to befriend %1">,
> + InGroup<CXX11>;
> +def warn_cxx98_compat_unelaborated_friend_type : Warning<
> + "befriending %1 without '%select{struct|interface|union|class|enum}0' "
> + "keyword is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
> +def err_qualified_friend_not_found : Error<
> + "no function named %0 with type %1 was found in the specified scope">;
> +def err_introducing_special_friend : Error<
> "must use a qualified name when declaring a %select{constructor|"
> "destructor|conversion operator}0 as a friend">;
> def err_tagless_friend_type_template : Error<
> @@ -1114,14 +1115,14 @@
> def err_constructor_return_type : Error<
> "constructor cannot have a return type">;
> def err_constructor_redeclared : Error<"constructor cannot be redeclared">;
> -def err_constructor_byvalue_arg : Error<
> - "copy constructor must pass its first argument by reference">;
> -def warn_no_constructor_for_refconst : Warning<
> - "%select{struct|union|class|enum}0 %1 does not declare any constructor to "
> - "initialize its non-modifiable members">;
> -def note_refconst_member_not_initialized : Note<
> - "%select{const|reference}0 member %1 will never be initialized">;
> -def ext_ms_explicit_constructor_call : ExtWarn<
> +def err_constructor_byvalue_arg : Error<
> + "copy constructor must pass its first argument by reference">;
> +def warn_no_constructor_for_refconst : Warning<
> + "%select{struct|interface|union|class|enum}0 %1 does not declare any "
> + "constructor to initialize its non-modifiable members">;
> +def note_refconst_member_not_initialized : Note<
> + "%select{const|reference}0 member %1 will never be initialized">;
> +def ext_ms_explicit_constructor_call : ExtWarn<
> "explicit constructor calls are a Microsoft extension">, InGroup<Microsoft>;
>
> // C++ destructors
> @@ -1308,15 +1309,16 @@
> def err_illegal_decl_array_of_auto : Error<
> "'%0' declared as array of %1">;
> def err_new_array_of_auto : Error<
> - "cannot allocate array of 'auto'">;
> -def err_auto_not_allowed : Error<
> - "'auto' not allowed %select{in function prototype|in non-static struct member"
> - "|in non-static union member|in non-static class member|in exception declaration"
> - "|in template parameter|in block literal|in template argument"
> - "|in typedef|in type alias|in function return type|here}0">;
> -def err_auto_var_requires_init : Error<
> - "declaration of variable %0 with type %1 requires an initializer">;
> -def err_auto_new_requires_ctor_arg : Error<
> + "cannot allocate array of 'auto'">;
> +def err_auto_not_allowed : Error<
> + "'auto' not allowed %select{in function prototype|in non-static struct member"
> + "|in non-static union member|in non-static class member|in interface member"
> + "|in exception declaration|in template parameter|in block literal"
> + "|in template argument|in typedef|in type alias|in function return type"
> + "|here}0">;
> +def err_auto_var_requires_init : Error<
> + "declaration of variable %0 with type %1 requires an initializer">;
> +def err_auto_new_requires_ctor_arg : Error<
> "new expression for type %0 requires a constructor argument">;
> def err_auto_new_requires_parens : Error<
> "new expression for type %0 cannot use list-initialization">;
> @@ -1436,13 +1438,13 @@
> "'constexpr' specifier is incompatible with C++98">,
> InGroup<CXX98Compat>, DefaultIgnore;
> def err_invalid_constexpr : Error<
> - "%select{function parameter|typedef|non-static data member}0 "
> - "cannot be constexpr">;
> -def err_constexpr_tag : Error<
> - "%select{class|struct|union|enum}0 cannot be marked constexpr">;
> -def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">;
> -def err_constexpr_no_declarators : Error<
> - "constexpr can only be used in variable and function declarations">;
> + "%select{function parameter|typedef|non-static data member}0 "
> + "cannot be constexpr">;
> +def err_constexpr_tag : Error<
> + "%select{class|struct|interface|union|enum}0 cannot be marked constexpr">;
> +def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">;
> +def err_constexpr_no_declarators : Error<
> + "constexpr can only be used in variable and function declarations">;
> def err_invalid_constexpr_var_decl : Error<
> "constexpr variable declaration must be a definition">;
> def err_constexpr_static_mem_var_requires_init : Error<
> @@ -1454,17 +1456,18 @@
> def err_constexpr_redecl_mismatch : Error<
> "%select{non-constexpr declaration of %0 follows constexpr declaration"
> "|constexpr declaration of %0 follows non-constexpr declaration}1">;
> -def err_constexpr_virtual : Error<"virtual function cannot be constexpr">;
> -def err_constexpr_virtual_base : Error<
> - "constexpr %select{member function|constructor}0 not allowed in "
> - "%select{class|struct}1 with virtual base %plural{1:class|:classes}2">;
> -def note_non_literal_incomplete : Note<
> - "incomplete type %0 is not a literal type">;
> -def note_non_literal_virtual_base : Note<"%select{class|struct}0 with virtual "
> - "base %plural{1:class|:classes}1 is not a literal type">;
> -def note_constexpr_virtual_base_here : Note<"virtual base class declared here">;
> -def err_constexpr_non_literal_return : Error<
> - "constexpr function's return type %0 is not a literal type">;
> +def err_constexpr_virtual : Error<"virtual function cannot be constexpr">;
> +def err_constexpr_virtual_base : Error<
> + "constexpr %select{member function|constructor}0 not allowed in "
> + "%select{struct|interface|class}1 with virtual base "
> + "%plural{1:class|:classes}2">;
> +def note_non_literal_incomplete : Note<
> + "incomplete type %0 is not a literal type">;
> +def note_non_literal_virtual_base : Note<"%select{struct|interface|class}0 "
> + "with virtual base %plural{1:class|:classes}1 is not a literal type">;
> +def note_constexpr_virtual_base_here : Note<"virtual base class declared here">;
> +def err_constexpr_non_literal_return : Error<
> + "constexpr function's return type %0 is not a literal type">;
> def err_constexpr_non_literal_param : Error<
> "constexpr %select{function|constructor}1's %ordinal0 parameter type %2 is "
> "not a literal type">;
> @@ -1697,13 +1700,15 @@
> "__declspec attribute %0 is not supported">,
> InGroup<IgnoredAttributes>;
> def warn_attribute_invalid_on_stmt : Warning<
> - "attribute %0 cannot be specified on a statement">,
> - InGroup<IgnoredAttributes>;
> -def warn_declspec_attribute_ignored : Warning<
> - "attribute %0 is ignored, place it after \"%select{class|struct|union|enum}1\" to apply attribute to type declaration">, InGroup<IgnoredAttributes>;
> -def warn_attribute_precede_definition : Warning<
> - "attribute declaration must precede definition">,
> - InGroup<IgnoredAttributes>;
> + "attribute %0 cannot be specified on a statement">,
> + InGroup<IgnoredAttributes>;
> +def warn_declspec_attribute_ignored : Warning<
> + "attribute %0 is ignored, place it after "
> + "\"%select{class|struct|union|interface|enum}1\" to apply attribute to "
> + "type declaration">, InGroup<IgnoredAttributes>;
> +def warn_attribute_precede_definition : Warning<
> + "attribute declaration must precede definition">,
> + InGroup<IgnoredAttributes>;
> def warn_attribute_void_function_method : Warning<
> "attribute %0 cannot be applied to "
> "%select{functions|Objective-C method}1 without return value">,
> @@ -3178,30 +3183,31 @@
> def err_tag_reference_non_tag : Error<
> "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template|a type alias template}0">;
> def err_tag_reference_conflict : Error<
> - "implicit declaration introduced by elaborated type conflicts with "
> - "%select{a declaration|a typedef|a type alias|a template}0 of the same name">;
> -def err_dependent_tag_decl : Error<
> - "%select{declaration|definition}0 of %select{struct|union|class|enum}1 "
> - "in a dependent scope">;
> -def err_tag_definition_of_typedef : Error<
> - "definition of type %0 conflicts with %select{typedef|type alias}1 of the same name">;
> -def err_conflicting_types : Error<"conflicting types for %0">;
> + "implicit declaration introduced by elaborated type conflicts with "
> + "%select{a declaration|a typedef|a type alias|a template}0 of the same name">;
> +def err_dependent_tag_decl : Error<
> + "%select{declaration|definition}0 of "
> + "%select{struct|interface|union|class|enum}1 in a dependent scope">;
> +def err_tag_definition_of_typedef : Error<
> + "definition of type %0 conflicts with %select{typedef|type alias}1 of the same name">;
> +def err_conflicting_types : Error<"conflicting types for %0">;
> def err_nested_redefinition : Error<"nested redefinition of %0">;
> -def err_use_with_wrong_tag : Error<
> - "use of %0 with tag type that does not match previous declaration">;
> -def warn_struct_class_tag_mismatch : Warning<
> - "%select{struct|class}0%select{| template}1 %2 was previously declared "
> - "as a %select{class|struct}0%select{| template}1">,
> - InGroup<MismatchedTags>, DefaultIgnore;
> -def warn_struct_class_previous_tag_mismatch : Warning<
> - "%2 defined as a %select{struct|class}0%select{| template}1 here but "
> - "previously declared as a %select{class|struct}0%select{| template}1">,
> - InGroup<MismatchedTags>, DefaultIgnore;
> -def note_struct_class_suggestion : Note<
> - "did you mean %select{struct|class}0 here?">;
> -def ext_forward_ref_enum : Extension<
> - "ISO C forbids forward references to 'enum' types">;
> -def err_forward_ref_enum : Error<
> +def err_use_with_wrong_tag : Error<
> + "use of %0 with tag type that does not match previous declaration">;
> +def warn_struct_class_tag_mismatch : Warning<
> + "%select{struct|interface|class}0%select{| template}1 %2 was previously "
> + "declared as a %select{struct|interface|class}3%select{| template}1">,
> + InGroup<MismatchedTags>, DefaultIgnore;
> +def warn_struct_class_previous_tag_mismatch : Warning<
> + "%2 defined as %select{a struct|an interface|a class}0%select{| template}1 "
> + "here but previously declared as "
> + "%select{a struct|an interface|a class}3%select{| template}1">,
> + InGroup<MismatchedTags>, DefaultIgnore;
> +def note_struct_class_suggestion : Note<
> + "did you mean %select{struct|interface|class}0 here?">;
> +def ext_forward_ref_enum : Extension<
> + "ISO C forbids forward references to 'enum' types">;
> +def err_forward_ref_enum : Error<
> "ISO C++ forbids forward references to 'enum' types">;
> def ext_ms_forward_ref_enum : Extension<
> "forward references to 'enum' types are a Microsoft extension">, InGroup<Microsoft>;
> @@ -3239,17 +3245,19 @@
> def warn_array_new_too_large : Warning<"array is too large (%0 elements)">,
> // FIXME PR11644: ", will throw std::bad_array_new_length at runtime"
> InGroup<DiagGroup<"bad-array-new-length">>;
> -
> -// -Wpadded, -Wpacked
> -def warn_padded_struct_field : Warning<
> - "padding %select{struct|class}0 %1 with %2 %select{byte|bit}3%select{|s}4 "
> - "to align %5">, InGroup<Padded>, DefaultIgnore;
> -def warn_padded_struct_anon_field : Warning<
> - "padding %select{struct|class}0 %1 with %2 %select{byte|bit}3%select{|s}4 "
> - "to align anonymous bit-field">, InGroup<Padded>, DefaultIgnore;
> -def warn_padded_struct_size : Warning<
> - "padding size of %0 with %1 %select{byte|bit}2%select{|s}3 "
> - "to alignment boundary">, InGroup<Padded>, DefaultIgnore;
> +
> +// -Wpadded, -Wpacked
> +def warn_padded_struct_field : Warning<
> + "padding %select{struct|interface|class}0 %1 with %2 "
> + "%select{byte|bit}3%select{|s}4 to align %5">,
> + InGroup<Padded>, DefaultIgnore;
> +def warn_padded_struct_anon_field : Warning<
> + "padding %select{struct|interface|class}0 %1 with %2 "
> + "%select{byte|bit}3%select{|s}4 to align anonymous bit-field">,
> + InGroup<Padded>, DefaultIgnore;
> +def warn_padded_struct_size : Warning<
> + "padding size of %0 with %1 %select{byte|bit}2%select{|s}3 "
> + "to alignment boundary">, InGroup<Padded>, DefaultIgnore;
> def warn_unnecessary_packed : Warning<
> "packed attribute is unnecessary for %0">, InGroup<Packed>, DefaultIgnore;
>
> @@ -3491,20 +3499,22 @@
> def ext_flexible_array_in_array : Extension<
> "%0 may not be used as an array element due to flexible array member">,
> InGroup<FlexibleArrayExtensions>;
> -def err_flexible_array_init : Error<
> - "initialization of flexible array member is not allowed">;
> -def ext_flexible_array_empty_aggregate_ms : Extension<
> - "flexible array member %0 in otherwise empty %select{struct|class}1 "
> - "is a Microsoft extension">, InGroup<Microsoft>;
> -def ext_flexible_array_union_ms : Extension<
> - "flexible array member %0 in a union is a Microsoft extension">,
> - InGroup<Microsoft>;
> -def ext_flexible_array_empty_aggregate_gnu : Extension<
> - "flexible array member %0 in otherwise empty %select{struct|class}1 "
> - "is a GNU extension">, InGroup<GNU>;
> -def ext_flexible_array_union_gnu : Extension<
> - "flexible array member %0 in a union is a GNU extension">, InGroup<GNU>;
> -
> +def err_flexible_array_init : Error<
> + "initialization of flexible array member is not allowed">;
> +def ext_flexible_array_empty_aggregate_ms : Extension<
> + "flexible array member %0 in otherwise empty "
> + "%select{struct|interface|union|class|enum}1 is a Microsoft extension">,
> + InGroup<Microsoft>;
> +def ext_flexible_array_union_ms : Extension<
> + "flexible array member %0 in a union is a Microsoft extension">,
> + InGroup<Microsoft>;
> +def ext_flexible_array_empty_aggregate_gnu : Extension<
> + "flexible array member %0 in otherwise empty "
> + "%select{struct|interface|union|class|enum}1 is a GNU extension">,
> + InGroup<GNU>;
> +def ext_flexible_array_union_gnu : Extension<
> + "flexible array member %0 in a union is a GNU extension">, InGroup<GNU>;
> +
> let CategoryName = "ARC Semantic Issue" in {
>
> // ARC-mode diagnostics.
> @@ -4584,13 +4594,13 @@
> "because namespace %1 does not enclose namespace %2">;
> def err_invalid_declarator_global_scope : Error<
> "definition or redeclaration of %0 cannot name the global scope">;
> -def err_invalid_declarator_in_function : Error<
> - "definition or redeclaration of %0 not allowed inside a function">;
> -def err_not_tag_in_scope : Error<
> - "no %select{struct|union|class|enum}0 named %1 in %2">;
> -
> -def err_no_typeid_with_fno_rtti : Error<
> - "cannot use typeid with -fno-rtti">;
> +def err_invalid_declarator_in_function : Error<
> + "definition or redeclaration of %0 not allowed inside a function">;
> +def err_not_tag_in_scope : Error<
> + "no %select{struct|interface|union|class|enum}0 named %1 in %2">;
> +
> +def err_no_typeid_with_fno_rtti : Error<
> + "cannot use typeid with -fno-rtti">;
>
> def err_cannot_form_pointer_to_member_of_reference_type : Error<
> "cannot form a pointer-to-member to member %0 of reference type %1">;
> @@ -5935,13 +5945,13 @@
> "%select{template|partial|member}0 specialization cannot be "
> "declared __module_private__">;
> def err_module_private_local : Error<
> - "%select{local variable|parameter|typedef}0 %1 cannot be declared "
> - "__module_private__">;
> -def err_module_private_local_class : Error<
> - "local %select{struct|union|class|enum}0 cannot be declared "
> - "__module_private__">;
> -def err_module_private_definition : Error<
> - "definition of %0 must be imported before it is required">;
> + "%select{local variable|parameter|typedef}0 %1 cannot be declared "
> + "__module_private__">;
> +def err_module_private_local_class : Error<
> + "local %select{struct|interface|union|class|enum}0 cannot be declared "
> + "__module_private__">;
> +def err_module_private_definition : Error<
> + "definition of %0 must be imported before it is required">;
> }
>
> let CategoryName = "Documentation Issue" in {
>
> Modified: cfe/trunk/include/clang/Basic/Specifiers.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Specifiers.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/Specifiers.h (original)
> +++ cfe/trunk/include/clang/Basic/Specifiers.h Fri Aug 31 13:45:21 2012
> @@ -50,12 +50,13 @@
> TST_decimal64, // _Decimal64
> TST_decimal128, // _Decimal128
> TST_enum,
> - TST_union,
> - TST_struct,
> - TST_class, // C++ class type
> - TST_typename, // Typedef, C++ class-name or enum name, etc.
> - TST_typeofType,
> - TST_typeofExpr,
> + TST_union,
> + TST_struct,
> + TST_class, // C++ class type
> + TST_interface, // C++ (Microsoft-specific) __interface type
> + TST_typename, // Typedef, C++ class-name or enum name, etc.
> + TST_typeofType,
> + TST_typeofExpr,
> TST_decltype, // C++0x decltype
> TST_underlyingType, // __underlying_type for C++0x
> TST_auto, // C++0x auto
>
> Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
> +++ cfe/trunk/include/clang/Basic/TokenKinds.def Fri Aug 31 13:45:21 2012
> @@ -505,6 +505,7 @@
> KEYWORD(__single_inheritance , KEYMS)
> KEYWORD(__multiple_inheritance , KEYMS)
> KEYWORD(__virtual_inheritance , KEYMS)
> +KEYWORD(__interface , KEYMS)
> ALIAS("__int8" , char , KEYMS)
> ALIAS("__int16" , short , KEYMS)
> ALIAS("__int32" , int , KEYMS)
> @@ -518,7 +519,6 @@
> ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND)
> ALIAS("_inline" , inline , KEYMS)
> ALIAS("_declspec" , __declspec , KEYMS)
> -ALIAS("__interface" , struct , KEYMS)
>
> // Borland Extensions which should be disabled in strict conformance mode.
> ALIAS("_pascal" , __pascal , KEYBORLAND)
>
> Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
> +++ cfe/trunk/include/clang/Sema/DeclSpec.h Fri Aug 31 13:45:21 2012
> @@ -266,6 +266,7 @@
> static const TST TST_enum = clang::TST_enum;
> static const TST TST_union = clang::TST_union;
> static const TST TST_struct = clang::TST_struct;
> + static const TST TST_interface = clang::TST_interface;
> static const TST TST_class = clang::TST_class;
> static const TST TST_typename = clang::TST_typename;
> static const TST TST_typeofType = clang::TST_typeofType;
> @@ -378,7 +379,8 @@
> }
> static bool isDeclRep(TST T) {
> return (T == TST_enum || T == TST_struct ||
> - T == TST_union || T == TST_class);
> + T == TST_interface || T == TST_union ||
> + T == TST_class);
> }
>
> DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT
>
> Modified: cfe/trunk/lib/AST/DeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclCXX.cpp (original)
> +++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Aug 31 13:45:21 2012
> @@ -463,13 +463,14 @@
> }
>
> void CXXRecordDecl::addedMember(Decl *D) {
> - if (!D->isImplicit() &&
> - !isa<FieldDecl>(D) &&
> - !isa<IndirectFieldDecl>(D) &&
> - (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class))
> - data().HasOnlyCMembers = false;
> -
> - // Ignore friends and invalid declarations.
> + if (!D->isImplicit() &&
> + !isa<FieldDecl>(D) &&
> + !isa<IndirectFieldDecl>(D) &&
> + (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class ||
> + cast<TagDecl>(D)->getTagKind() == TTK_Interface))
> + data().HasOnlyCMembers = false;
> +
> + // Ignore friends and invalid declarations.
> if (D->getFriendObjectKind() || D->isInvalidDecl())
> return;
>
> @@ -933,13 +934,14 @@
> if (Shadow->getDeclName().getNameKind()
> == DeclarationName::CXXConversionFunctionName)
> data().Conversions.addDecl(Shadow, Shadow->getAccess());
> -}
> -
> -bool CXXRecordDecl::isCLike() const {
> - if (getTagKind() == TTK_Class || !TemplateOrInstantiation.isNull())
> - return false;
> - if (!hasDefinition())
> - return true;
> +}
> +
> +bool CXXRecordDecl::isCLike() const {
> + if (getTagKind() == TTK_Class || getTagKind() == TTK_Interface ||
> + !TemplateOrInstantiation.isNull())
> + return false;
> + if (!hasDefinition())
> + return true;
>
> return isPOD() && data().HasOnlyCMembers;
> }
>
> Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
> +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Fri Aug 31 13:45:21 2012
> @@ -1270,12 +1270,13 @@
> void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
> switch (T->getDecl()->getTagKind()) {
> case TTK_Union:
> - Out << 'T';
> - break;
> - case TTK_Struct:
> - Out << 'U';
> - break;
> - case TTK_Class:
> + Out << 'T';
> + break;
> + case TTK_Struct:
> + case TTK_Interface:
> + Out << 'U';
> + break;
> + case TTK_Class:
> Out << 'V';
> break;
> case TTK_Enum:
>
> Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
> +++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Fri Aug 31 13:45:21 2012
> @@ -2260,12 +2260,28 @@
> }
>
> // Use the externally-supplied field offset.
> - return ExternalFieldOffset;
> -}
> -
> -void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
> - uint64_t UnpaddedOffset,
> - uint64_t UnpackedOffset,
> + return ExternalFieldOffset;
> +}
> +
> +/// \brief Get diagnostic %select index for tag kind for
> +/// field padding diagnostic message.
> +/// WARNING: Indexes apply to particular diagnostics only!
> +///
> +/// \returns diagnostic %select index.
> +static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)
> +{
> + switch (Tag) {
> + case TTK_Struct: return 0;
> + case TTK_Interface: return 1;
> + case TTK_Class: return 2;
> + default: assert("Invalid tag kind for field padding diagnostic!");
> + }
> + return -1;
> +}
> +
> +void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
> + uint64_t UnpaddedOffset,
> + uint64_t UnpackedOffset,
> unsigned UnpackedAlign,
> bool isPacked,
> const FieldDecl *D) {
> @@ -2288,20 +2304,20 @@
> if (PadSize % CharBitNum == 0) {
> PadSize = PadSize / CharBitNum;
> InBits = false;
> - }
> - if (D->getIdentifier())
> - Diag(D->getLocation(), diag::warn_padded_struct_field)
> - << (D->getParent()->isStruct() ? 0 : 1) // struct|class
> - << Context.getTypeDeclType(D->getParent())
> - << PadSize
> - << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not
> - << D->getIdentifier();
> - else
> - Diag(D->getLocation(), diag::warn_padded_struct_anon_field)
> - << (D->getParent()->isStruct() ? 0 : 1) // struct|class
> - << Context.getTypeDeclType(D->getParent())
> - << PadSize
> - << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
> + }
> + if (D->getIdentifier())
> + Diag(D->getLocation(), diag::warn_padded_struct_field)
> + << getPaddingDiagFromTagKind(D->getParent()->getTagKind())
> + << Context.getTypeDeclType(D->getParent())
> + << PadSize
> + << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not
> + << D->getIdentifier();
> + else
> + Diag(D->getLocation(), diag::warn_padded_struct_anon_field)
> + << getPaddingDiagFromTagKind(D->getParent()->getTagKind())
> + << Context.getTypeDeclType(D->getParent())
> + << PadSize
> + << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
> }
>
> // Warn if we packed it unnecessarily. If the alignment is 1 byte don't
>
> Modified: cfe/trunk/lib/AST/Type.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/Type.cpp (original)
> +++ cfe/trunk/lib/AST/Type.cpp Fri Aug 31 13:45:21 2012
> @@ -357,9 +357,15 @@
> return RT->getDecl()->isStruct();
> return false;
> }
> +bool Type::isInterfaceType() const {
> + if (const RecordType *RT = getAs<RecordType>())
> + return RT->getDecl()->isInterface();
> + return false;
> +}
> bool Type::isStructureOrClassType() const {
> if (const RecordType *RT = getAs<RecordType>())
> - return RT->getDecl()->isStruct() || RT->getDecl()->isClass();
> + return RT->getDecl()->isStruct() || RT->getDecl()->isClass() ||
> + RT->getDecl()->isInterface();
> return false;
> }
> bool Type::isVoidPointerType() const {
> @@ -1317,6 +1323,7 @@
> case TST_typename: return ETK_Typename;
> case TST_class: return ETK_Class;
> case TST_struct: return ETK_Struct;
> + case TST_interface: return ETK_Interface;
> case TST_union: return ETK_Union;
> case TST_enum: return ETK_Enum;
> }
> @@ -1327,6 +1334,7 @@
> switch(TypeSpec) {
> case TST_class: return TTK_Class;
> case TST_struct: return TTK_Struct;
> + case TST_interface: return TTK_Interface;
> case TST_union: return TTK_Union;
> case TST_enum: return TTK_Enum;
> }
> @@ -1339,6 +1347,7 @@
> switch (Kind) {
> case TTK_Class: return ETK_Class;
> case TTK_Struct: return ETK_Struct;
> + case TTK_Interface: return ETK_Interface;
> case TTK_Union: return ETK_Union;
> case TTK_Enum: return ETK_Enum;
> }
> @@ -1350,6 +1359,7 @@
> switch (Keyword) {
> case ETK_Class: return TTK_Class;
> case ETK_Struct: return TTK_Struct;
> + case ETK_Interface: return TTK_Interface;
> case ETK_Union: return TTK_Union;
> case ETK_Enum: return TTK_Enum;
> case ETK_None: // Fall through.
> @@ -1367,6 +1377,7 @@
> return false;
> case ETK_Class:
> case ETK_Struct:
> + case ETK_Interface:
> case ETK_Union:
> case ETK_Enum:
> return true;
> @@ -1381,6 +1392,7 @@
> case ETK_Typename: return "typename";
> case ETK_Class: return "class";
> case ETK_Struct: return "struct";
> + case ETK_Interface: return "__interface";
> case ETK_Union: return "union";
> case ETK_Enum: return "enum";
> }
>
> Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Fri Aug 31 13:45:21 2012
> @@ -520,13 +520,13 @@
> const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
> unsigned Tag = 0;
> if (CXXDecl) {
> - RDName = getClassName(RD);
> - Tag = llvm::dwarf::DW_TAG_class_type;
> - }
> - else if (RD->isStruct())
> - Tag = llvm::dwarf::DW_TAG_structure_type;
> - else if (RD->isUnion())
> - Tag = llvm::dwarf::DW_TAG_union_type;
> + RDName = getClassName(RD);
> + Tag = llvm::dwarf::DW_TAG_class_type;
> + }
> + else if (RD->isStruct() || RD->isInterface())
> + Tag = llvm::dwarf::DW_TAG_structure_type;
> + else if (RD->isUnion())
> + Tag = llvm::dwarf::DW_TAG_union_type;
> else
> llvm_unreachable("Unknown RecordDecl type!");
>
>
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Aug 31 13:45:21 2012
> @@ -1875,6 +1875,9 @@
> TagName="union" ; FixitTagName = "union " ;TagKind=tok::kw_union ;break;
> case DeclSpec::TST_struct:
> TagName="struct"; FixitTagName = "struct ";TagKind=tok::kw_struct;break;
> + case DeclSpec::TST_interface:
> + TagName="__interface"; FixitTagName = "__interface ";
> + TagKind=tok::kw___interface;break;
> case DeclSpec::TST_class:
> TagName="class" ; FixitTagName = "class " ;TagKind=tok::kw_class ;break;
> }
> @@ -2709,6 +2712,7 @@
> // class-specifier:
> case tok::kw_class:
> case tok::kw_struct:
> + case tok::kw___interface:
> case tok::kw_union: {
> tok::TokenKind Kind = Tok.getKind();
> ConsumeToken();
> @@ -3531,6 +3535,7 @@
> // struct-or-union-specifier (C99) or class-specifier (C++)
> case tok::kw_class:
> case tok::kw_struct:
> + case tok::kw___interface:
> case tok::kw_union:
> // enum-specifier
> case tok::kw_enum:
> @@ -3602,6 +3607,7 @@
> // struct-or-union-specifier (C99) or class-specifier (C++)
> case tok::kw_class:
> case tok::kw_struct:
> + case tok::kw___interface:
> case tok::kw_union:
> // enum-specifier
> case tok::kw_enum:
> @@ -3740,6 +3746,7 @@
> case tok::kw_class:
> case tok::kw_struct:
> case tok::kw_union:
> + case tok::kw___interface:
> // enum-specifier
> case tok::kw_enum:
>
>
> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Aug 31 13:45:21 2012
> @@ -1031,12 +1031,14 @@
> const ParsedTemplateInfo &TemplateInfo,
> AccessSpecifier AS,
> bool EnteringContext, DeclSpecContext DSC) {
> - DeclSpec::TST TagType;
> - if (TagTokKind == tok::kw_struct)
> - TagType = DeclSpec::TST_struct;
> - else if (TagTokKind == tok::kw_class)
> - TagType = DeclSpec::TST_class;
> - else {
> + DeclSpec::TST TagType;
> + if (TagTokKind == tok::kw_struct)
> + TagType = DeclSpec::TST_struct;
> + else if (TagTokKind == tok::kw___interface)
> + TagType = DeclSpec::TST_interface;
> + else if (TagTokKind == tok::kw_class)
> + TagType = DeclSpec::TST_class;
> + else {
> assert(TagTokKind == tok::kw_union && "Not a class specifier");
> TagType = DeclSpec::TST_union;
> }
> @@ -1148,13 +1150,14 @@
> }
>
> Diag(NameLoc, diag::err_explicit_spec_non_template)
> - << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
> - << (TagType == DeclSpec::TST_class? 0
> - : TagType == DeclSpec::TST_struct? 1
> - : 2)
> - << Name
> - << SourceRange(LAngleLoc, RAngleLoc);
> -
> + << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
> + << (TagType == DeclSpec::TST_class? 0
> + : TagType == DeclSpec::TST_struct? 1
> + : TagType == DeclSpec::TST_interface? 2
> + : 3)
> + << Name
> + << SourceRange(LAngleLoc, RAngleLoc);
> +
> // Strip off the last template parameter list if it was empty, since
> // we've removed its template argument list.
> if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
> @@ -1240,14 +1243,13 @@
> (Tok.is(tok::semi) ||
> (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) {
> TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
> - if (Tok.isNot(tok::semi)) {
> - // A semicolon was missing after this declaration. Diagnose and recover.
> - ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
> - TagType == DeclSpec::TST_class ? "class" :
> - TagType == DeclSpec::TST_struct ? "struct" : "union");
> - PP.EnterToken(Tok);
> - Tok.setKind(tok::semi);
> - }
> + if (Tok.isNot(tok::semi)) {
> + // A semicolon was missing after this declaration. Diagnose and recover.
> + ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
> + DeclSpec::getSpecifierName(TagType));
> + PP.EnterToken(Tok);
> + Tok.setKind(tok::semi);
> + }
> } else
> TUK = Sema::TUK_Reference;
>
> @@ -1466,14 +1468,13 @@
> // Also enforce C++ [temp]p3:
> // In a template-declaration which defines a class, no declarator
> // is permitted.
> - if (TUK == Sema::TUK_Definition &&
> - (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {
> - ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
> - TagType == DeclSpec::TST_class ? "class" :
> - TagType == DeclSpec::TST_struct ? "struct" : "union");
> - // Push this token back into the preprocessor and change our current token
> - // to ';' so that the rest of the code recovers as though there were an
> - // ';' after the definition.
> + if (TUK == Sema::TUK_Definition &&
> + (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {
> + ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
> + DeclSpec::getSpecifierName(TagType));
> + // Push this token back into the preprocessor and change our current token
> + // to ';' so that the rest of the code recovers as though there were an
> + // ';' after the definition.
> PP.EnterToken(Tok);
> Tok.setKind(tok::semi);
> }
> @@ -2236,12 +2237,13 @@
> /// member-declaration member-specification[opt]
> /// access-specifier ':' member-specification[opt]
> ///
> -void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
> - unsigned TagType, Decl *TagDecl) {
> - assert((TagType == DeclSpec::TST_struct ||
> - TagType == DeclSpec::TST_union ||
> - TagType == DeclSpec::TST_class) && "Invalid TagType!");
> -
> +void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
> + unsigned TagType, Decl *TagDecl) {
> + assert((TagType == DeclSpec::TST_struct ||
> + TagType == DeclSpec::TST_interface ||
> + TagType == DeclSpec::TST_union ||
> + TagType == DeclSpec::TST_class) && "Invalid TagType!");
> +
> PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
> "parsing struct/union/class body");
>
>
> Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
> +++ cfe/trunk/lib/Sema/DeclSpec.cpp Fri Aug 31 13:45:21 2012
> @@ -270,6 +270,7 @@
> case TST_int:
> case TST_int128:
> case TST_struct:
> + case TST_interface:
> case TST_union:
> case TST_unknown_anytype:
> case TST_unspecified:
> @@ -400,6 +401,7 @@
> case DeclSpec::TST_class: return "class";
> case DeclSpec::TST_union: return "union";
> case DeclSpec::TST_struct: return "struct";
> + case DeclSpec::TST_interface: return "__interface";
> case DeclSpec::TST_typename: return "type-name";
> case DeclSpec::TST_typeofType:
> case DeclSpec::TST_typeofExpr: return "typeof";
>
> Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Fri Aug 31 13:45:21 2012
> @@ -1059,10 +1059,12 @@
> // Allow us to find class templates, too.
> if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
> ND = ClassTemplate->getTemplatedDecl();
> -
> +
> + // For purposes of this check, interfaces match too.
> if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
> return RD->getTagKind() == TTK_Class ||
> - RD->getTagKind() == TTK_Struct;
> + RD->getTagKind() == TTK_Struct ||
> + RD->getTagKind() == TTK_Interface;
>
> return false;
> }
> @@ -1422,7 +1424,8 @@
> if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
> switch (Tag->getTagKind()) {
> case TTK_Struct: return "struct <anonymous>";
> - case TTK_Class: return "class <anonymous>";
> + case TTK_Interface: return "__interface <anonymous>";
> + case TTK_Class: return "class <anonymous>";
> case TTK_Union: return "union <anonymous>";
> case TTK_Enum: return "enum <anonymous>";
> }
> @@ -1449,7 +1452,7 @@
> Policy,
> Allocator));
> Builder.AddTypedTextChunk("this");
> - Results.AddResult(CodeCompletionResult(Builder.TakeString()));
> + Results.AddResult(CodeCompletionResult(Builder.TakeString()));
> }
>
> /// \brief Add language constructs that show up for "ordinary" names.
> @@ -2884,6 +2887,7 @@
> default:
> if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
> switch (TD->getTagKind()) {
> + case TTK_Interface: // fall through
> case TTK_Struct: return CXCursor_StructDecl;
> case TTK_Class: return CXCursor_ClassDecl;
> case TTK_Union: return CXCursor_UnionDecl;
> @@ -3601,6 +3605,7 @@
>
> case DeclSpec::TST_struct:
> case DeclSpec::TST_class:
> + case DeclSpec::TST_interface:
> Filter = &ResultBuilder::IsClassOrStruct;
> ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
> break;
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Aug 31 13:45:21 2012
> @@ -350,8 +350,8 @@
> /// isTagName() - This method is called *for error recovery purposes only*
> /// to determine if the specified name is a valid tag name ("struct foo"). If
> /// so, this returns the TST for the tag corresponding to it (TST_enum,
> -/// TST_union, TST_struct, TST_class). This is used to diagnose cases in C
> -/// where the user forgot to specify the tag.
> +/// TST_union, TST_struct, TST_interface, TST_class). This is used to diagnose
> +/// cases in C where the user forgot to specify the tag.
> DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
> // Do a tag name lookup in this scope.
> LookupResult R(*this, &II, SourceLocation(), LookupTagName);
> @@ -361,6 +361,7 @@
> if (const TagDecl *TD = R.getAsSingle<TagDecl>()) {
> switch (TD->getTagKind()) {
> case TTK_Struct: return DeclSpec::TST_struct;
> + case TTK_Interface: return DeclSpec::TST_interface;
> case TTK_Union: return DeclSpec::TST_union;
> case TTK_Class: return DeclSpec::TST_class;
> case TTK_Enum: return DeclSpec::TST_enum;
> @@ -538,6 +539,11 @@
> FixItTagName = "struct ";
> break;
>
> + case TTK_Interface:
> + TagName = "__interface";
> + FixItTagName = "__interface ";
> + break;
> +
> case TTK_Union:
> TagName = "union";
> FixItTagName = "union ";
> @@ -2604,6 +2610,7 @@
> TagDecl *Tag = 0;
> if (DS.getTypeSpecType() == DeclSpec::TST_class ||
> DS.getTypeSpecType() == DeclSpec::TST_struct ||
> + DS.getTypeSpecType() == DeclSpec::TST_interface ||
> DS.getTypeSpecType() == DeclSpec::TST_union ||
> DS.getTypeSpecType() == DeclSpec::TST_enum) {
> TagD = DS.getRepAsDecl();
> @@ -2642,7 +2649,8 @@
> Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag)
> << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 :
> DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 :
> - DS.getTypeSpecType() == DeclSpec::TST_union ? 2 : 3);
> + DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 :
> + DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4);
> else
> Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators);
> // Don't emit warnings after this error.
> @@ -2763,6 +2771,7 @@
> DeclSpec::TST TypeSpecType = DS.getTypeSpecType();
> if (TypeSpecType == DeclSpec::TST_class ||
> TypeSpecType == DeclSpec::TST_struct ||
> + TypeSpecType == DeclSpec::TST_interface ||
> TypeSpecType == DeclSpec::TST_union ||
> TypeSpecType == DeclSpec::TST_enum) {
> AttributeList* attrs = DS.getAttributes().getList();
> @@ -2772,7 +2781,8 @@
> << attrs->getName()
> << (TypeSpecType == DeclSpec::TST_class ? 0 :
> TypeSpecType == DeclSpec::TST_struct ? 1 :
> - TypeSpecType == DeclSpec::TST_union ? 2 : 3);
> + TypeSpecType == DeclSpec::TST_union ? 2 :
> + TypeSpecType == DeclSpec::TST_interface ? 3 : 4);
> attrs = attrs->getNext();
> }
> }
> @@ -5185,6 +5195,14 @@
> NewFD->setImplicitlyInline();
> }
>
> + // if this is a method defined in an __interface, set pure
> + // (isVirtual will already return true)
> + if (CXXRecordDecl *Parent = dyn_cast<CXXRecordDecl>(
> + NewFD->getDeclContext())) {
> + if (Parent->getTagKind() == TTK_Interface)
> + NewFD->setPure(true);
> + }
> +
> SetNestedNameSpecifier(NewFD, D);
> isExplicitSpecialization = false;
> isFunctionTemplateSpecialization = false;
> @@ -8118,6 +8136,7 @@
> switch (D.getDeclSpec().getTypeSpecType()) {
> case TST_enum:
> case TST_struct:
> + case TST_interface:
> case TST_union:
> case TST_class: {
> TagDecl *tagFromDeclSpec = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
> @@ -8193,6 +8212,31 @@
> return false;
> }
>
> +/// \brief Get diagnostic %select index for tag kind for
> +/// redeclaration diagnostic message.
> +/// WARNING: Indexes apply to particular diagnostics only!
> +///
> +/// \returns diagnostic %select index.
> +static unsigned getRedeclDiagFromTagKind(TagTypeKind Tag)
> +{
> + switch (Tag) {
> + case TTK_Struct: return 0;
> + case TTK_Interface: return 1;
> + case TTK_Class: return 2;
> + default: assert("Invalid tag kind for redecl diagnostic!");
> + }
> + return -1;
> +}
> +
> +/// \brief Determine if tag kind is a class-key compatible with
> +/// class for redeclaration (class, struct, or __interface).
> +///
> +/// \returns true iff the tag kind is compatible.
> +static bool isClassCompatTagKind(TagTypeKind Tag)
> +{
> + return Tag == TTK_Struct || Tag == TTK_Class || Tag == TTK_Interface;
> +}
> +
> /// \brief Determine whether a tag with a given kind is acceptable
> /// as a redeclaration of the given tag declaration.
> ///
> @@ -8215,12 +8259,11 @@
> // struct class-key shall be used to refer to a class (clause 9)
> // declared using the class or struct class-key.
> TagTypeKind OldTag = Previous->getTagKind();
> - if (!isDefinition || (NewTag != TTK_Class && NewTag != TTK_Struct))
> + if (!isDefinition || !isClassCompatTagKind(NewTag))
> if (OldTag == NewTag)
> return true;
>
> - if ((OldTag == TTK_Struct || OldTag == TTK_Class) &&
> - (NewTag == TTK_Struct || NewTag == TTK_Class)) {
> + if (isClassCompatTagKind(OldTag) && isClassCompatTagKind(NewTag)) {
> // Warn about the struct/class tag mismatch.
> bool isTemplate = false;
> if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous))
> @@ -8230,7 +8273,8 @@
> // In a template instantiation, do not offer fix-its for tag mismatches
> // since they usually mess up the template instead of fixing the problem.
> Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
> - << (NewTag == TTK_Class) << isTemplate << &Name;
> + << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
> + << getRedeclDiagFromTagKind(OldTag);
> return true;
> }
>
> @@ -8249,13 +8293,13 @@
> if (!previousMismatch) {
> previousMismatch = true;
> Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch)
> - << (NewTag == TTK_Class) << isTemplate << &Name;
> + << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
> + << getRedeclDiagFromTagKind(I->getTagKind());
> }
> Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion)
> - << (NewTag == TTK_Class)
> + << getRedeclDiagFromTagKind(NewTag)
> << FixItHint::CreateReplacement(I->getInnerLocStart(),
> - NewTag == TTK_Class?
> - "class" : "struct");
> + TypeWithKeyword::getTagTypeKindName(NewTag));
> }
> }
> return true;
> @@ -8271,16 +8315,16 @@
> }
>
> Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
> - << (NewTag == TTK_Class)
> - << isTemplate << &Name;
> + << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name
> + << getRedeclDiagFromTagKind(OldTag);
> Diag(Redecl->getLocation(), diag::note_previous_use);
>
> // If there is a previous defintion, suggest a fix-it.
> if (Previous->getDefinition()) {
> Diag(NewTagLoc, diag::note_struct_class_suggestion)
> - << (Redecl->getTagKind() == TTK_Class)
> + << getRedeclDiagFromTagKind(Redecl->getTagKind())
> << FixItHint::CreateReplacement(SourceRange(NewTagLoc),
> - Redecl->getTagKind() == TTK_Class? "class" : "struct");
> + TypeWithKeyword::getTagTypeKindName(Redecl->getTagKind()));
> }
>
> return true;
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Aug 31 13:45:21 2012
> @@ -672,12 +672,28 @@
> isa<CXXConstructorDecl>(FD)))
> return false;
> }
> - return true;
> -}
> -
> -// CheckConstexprFunctionDecl - Check whether a function declaration satisfies
> -// the requirements of a constexpr function definition or a constexpr
> -// constructor definition. If so, return true. If not, produce appropriate
> + return true;
> +}
> +
> +/// \brief Get diagnostic %select index for tag kind for
> +/// record diagnostic message.
> +/// WARNING: Indexes apply to particular diagnostics only!
> +///
> +/// \returns diagnostic %select index.
> +static unsigned getRecordDiagFromTagKind(TagTypeKind Tag)
> +{
> + switch (Tag) {
> + case TTK_Struct: return 0;
> + case TTK_Interface: return 1;
> + case TTK_Class: return 2;
> + default: assert("Invalid tag kind for record diagnostic!");
> + }
> + return -1;
> +}
> +
> +// CheckConstexprFunctionDecl - Check whether a function declaration satisfies
> +// the requirements of a constexpr function definition or a constexpr
> +// constructor definition. If so, return true. If not, produce appropriate
> // diagnostics and return false.
> //
> // This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360.
> @@ -688,14 +704,14 @@
> // The definition of a constexpr constructor shall satisfy the following
> // constraints:
> // - the class shall not have any virtual base classes;
> - const CXXRecordDecl *RD = MD->getParent();
> - if (RD->getNumVBases()) {
> - Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base)
> - << isa<CXXConstructorDecl>(NewFD) << RD->isStruct()
> - << RD->getNumVBases();
> - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
> - E = RD->vbases_end(); I != E; ++I)
> - Diag(I->getLocStart(),
> + const CXXRecordDecl *RD = MD->getParent();
> + if (RD->getNumVBases()) {
> + Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base)
> + << isa<CXXConstructorDecl>(NewFD)
> + << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
> + for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
> + E = RD->vbases_end(); I != E; ++I)
> + Diag(I->getLocStart(),
> diag::note_constexpr_virtual_base_here) << I->getSourceRange();
> return false;
> }
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Aug 31 13:45:21 2012
> @@ -2998,7 +2998,7 @@
> case UTT_IsUnion:
> return T->isUnionType();
> case UTT_IsClass:
> - return T->isClassType() || T->isStructureType();
> + return T->isClassType() || T->isStructureType() || T->isInterfaceType();
> case UTT_IsFunction:
> return T->isFunctionType();
>
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Fri Aug 31 13:45:21 2012
> @@ -727,6 +727,7 @@
> case TST_enum:
> case TST_union:
> case TST_struct:
> + case TST_interface:
> case TST_class:
> case TST_auto:
> case TST_unknown_anytype:
>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Fri Aug 31 13:45:21 2012
> @@ -753,7 +753,8 @@
> case DeclSpec::TST_class:
> case DeclSpec::TST_enum:
> case DeclSpec::TST_union:
> - case DeclSpec::TST_struct: {
> + case DeclSpec::TST_struct:
> + case DeclSpec::TST_interface: {
> TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl());
> if (!D) {
> // This can happen in C++ with ambiguous lookups.
> @@ -1853,30 +1854,31 @@
> case TTK_Struct: Error = 1; /* Struct member */ break;
> case TTK_Union: Error = 2; /* Union member */ break;
> case TTK_Class: Error = 3; /* Class member */ break;
> + case TTK_Interface: Error = 4; /* Interface member */ break;
> }
> break;
> case Declarator::CXXCatchContext:
> case Declarator::ObjCCatchContext:
> - Error = 4; // Exception declaration
> + Error = 5; // Exception declaration
> break;
> case Declarator::TemplateParamContext:
> - Error = 5; // Template parameter
> + Error = 6; // Template parameter
> break;
> case Declarator::BlockLiteralContext:
> - Error = 6; // Block literal
> + Error = 7; // Block literal
> break;
> case Declarator::TemplateTypeArgContext:
> - Error = 7; // Template type argument
> + Error = 8; // Template type argument
> break;
> case Declarator::AliasDeclContext:
> case Declarator::AliasTemplateContext:
> - Error = 9; // Type alias
> + Error = 10; // Type alias
> break;
> case Declarator::TrailingReturnContext:
> - Error = 10; // Function return type
> + Error = 11; // Function return type
> break;
> case Declarator::TypeNameContext:
> - Error = 11; // Generic
> + Error = 12; // Generic
> break;
> case Declarator::FileContext:
> case Declarator::BlockContext:
> @@ -1887,11 +1889,11 @@
> }
>
> if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
> - Error = 8;
> + Error = 9;
>
> // In Objective-C it is an error to use 'auto' on a function declarator.
> if (D.isFunctionDeclarator())
> - Error = 10;
> + Error = 11;
>
> // C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator
> // contains a trailing return type. That is only legal at the outermost
> @@ -4430,6 +4432,22 @@
> return RequireCompleteType(Loc, T, Diagnoser);
> }
>
> +/// \brief Get diagnostic %select index for tag kind for
> +/// literal type diagnostic message.
> +/// WARNING: Indexes apply to particular diagnostics only!
> +///
> +/// \returns diagnostic %select index.
> +static unsigned getLiteralDiagFromTagKind(TagTypeKind Tag)
> +{
> + switch (Tag) {
> + case TTK_Struct: return 0;
> + case TTK_Interface: return 1;
> + case TTK_Class: return 2;
> + default: assert("Invalid tag kind for literal type diagnostic!");
> + }
> + return -1;
> +}
> +
> /// @brief Ensure that the type T is a literal type.
> ///
> /// This routine checks whether the type @p T is a literal type. If @p T is an
> @@ -4486,7 +4504,7 @@
> // of constexpr constructors.
> if (RD->getNumVBases()) {
> Diag(RD->getLocation(), diag::note_non_literal_virtual_base)
> - << RD->isStruct() << RD->getNumVBases();
> + << getLiteralDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
> for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
> E = RD->vbases_end(); I != E; ++I)
> Diag(I->getLocStart(),
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Aug 31 13:45:21 2012
> @@ -1716,14 +1716,16 @@
> return true;
>
> // Compatible tags match.
> - if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {
> - TagDecl *TagY = cast<TagDecl>(Y);
> - return (TagX->getTagKind() == TagY->getTagKind()) ||
> - ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class) &&
> - (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class));
> - }
> -
> - // Functions with the same type and linkage match.
> + if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {
> + TagDecl *TagY = cast<TagDecl>(Y);
> + return (TagX->getTagKind() == TagY->getTagKind()) ||
> + ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class ||
> + TagX->getTagKind() == TTK_Interface) &&
> + (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class ||
> + TagY->getTagKind() == TTK_Interface));
> + }
> +
> + // Functions with the same type and linkage match.
> // FIXME: This needs to cope with function templates, merging of
> //prototyped/non-prototyped functions, etc.
> if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) {
>
> Modified: cfe/trunk/test/Parser/MicrosoftExtensions.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/test/Parser/MicrosoftExtensions.cpp (original)
> +++ cfe/trunk/test/Parser/MicrosoftExtensions.cpp Fri Aug 31 13:45:21 2012
> @@ -171,19 +171,27 @@
> int k = typename var;// expected-error {{expected a qualified name after 'typename'}}
> }
>
> -
> -__interface MicrosoftInterface;
> -__interface MicrosoftInterface {
> - virtual void foo1() = 0;
> - virtual void foo2() = 0;
> -};
> -
> -void interface_test() {
> - MicrosoftInterface* a;
> - a->foo1();
> -}
> -
> -__int64 x7 = __int64(0);
> +
> +__interface MicrosoftInterface;
> +__interface MicrosoftInterface {
> + void foo1() = 0;
> + virtual void foo2() = 0;
> +};
> +
> +__interface MicrosoftDerivedInterface : public MicrosoftInterface {
> + void foo1();
> + void foo2() override;
> + void foo3();
> +};
> +
> +void interface_test() {
> + MicrosoftInterface* a;
> + a->foo1();
> + MicrosoftDerivedInterface* b;
> + b->foo2();
> +}
> +
> +__int64 x7 = __int64(0);
>
>
> namespace If_exists_test {
>
> Modified: cfe/trunk/tools/libclang/CIndexCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexCXX.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/tools/libclang/CIndexCXX.cpp (original)
> +++ cfe/trunk/tools/libclang/CIndexCXX.cpp Fri Aug 31 13:45:21 2012
> @@ -64,14 +64,15 @@
>
> case CXCursor_ClassTemplatePartialSpecialization:
> if (ClassTemplateSpecializationDecl *PartialSpec
> - = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
> - getCursorDecl(C))) {
> - switch (PartialSpec->getTagKind()) {
> - case TTK_Class: return CXCursor_ClassDecl;
> - case TTK_Struct: return CXCursor_StructDecl;
> - case TTK_Union: return CXCursor_UnionDecl;
> - case TTK_Enum: return CXCursor_NoDeclFound;
> - }
> + = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
> + getCursorDecl(C))) {
> + switch (PartialSpec->getTagKind()) {
> + case TTK_Interface:
> + case TTK_Struct: return CXCursor_StructDecl;
> + case TTK_Class: return CXCursor_ClassDecl;
> + case TTK_Union: return CXCursor_UnionDecl;
> + case TTK_Enum: return CXCursor_NoDeclFound;
> + }
> }
> break;
>
>
> Modified: cfe/trunk/tools/libclang/CIndexUSRs.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexUSRs.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/tools/libclang/CIndexUSRs.cpp (original)
> +++ cfe/trunk/tools/libclang/CIndexUSRs.cpp Fri Aug 31 13:45:21 2012
> @@ -1,932 +1,935 @@
> -//===- CIndexUSR.cpp - Clang-C Source Indexing Library --------------------===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -//
> -// This file implements the generation and use of USRs from CXEntities.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#include "CIndexer.h"
> -#include "CXCursor.h"
> -#include "CXString.h"
> -#include "clang/AST/DeclTemplate.h"
> -#include "clang/AST/DeclVisitor.h"
> -#include "clang/Frontend/ASTUnit.h"
> -#include "clang/Lex/PreprocessingRecord.h"
> -#include "llvm/ADT/SmallString.h"
> -#include "llvm/Support/raw_ostream.h"
> -
> -using namespace clang;
> -using namespace clang::cxstring;
> -
> -//===----------------------------------------------------------------------===//
> -// USR generation.
> -//===----------------------------------------------------------------------===//
> -
> -namespace {
> -class USRGenerator : public DeclVisitor<USRGenerator> {
> - OwningPtr<SmallString<128> > OwnedBuf;
> - SmallVectorImpl<char> &Buf;
> - llvm::raw_svector_ostream Out;
> - bool IgnoreResults;
> - ASTContext *Context;
> - bool generatedLoc;
> -
> - llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
> -
> -public:
> - explicit USRGenerator(ASTContext *Ctx = 0, SmallVectorImpl<char> *extBuf = 0)
> - : OwnedBuf(extBuf ? 0 : new SmallString<128>()),
> - Buf(extBuf ? *extBuf : *OwnedBuf.get()),
> - Out(Buf),
> - IgnoreResults(false),
> - Context(Ctx),
> - generatedLoc(false)
> - {
> - // Add the USR space prefix.
> - Out << "c:";
> - }
> -
> - StringRef str() {
> - return Out.str();
> - }
> -
> - USRGenerator* operator->() { return this; }
> -
> - template <typename T>
> - llvm::raw_svector_ostream &operator<<(const T &x) {
> - Out << x;
> - return Out;
> - }
> -
> - bool ignoreResults() const { return IgnoreResults; }
> -
> - // Visitation methods from generating USRs from AST elements.
> - void VisitDeclContext(DeclContext *D);
> - void VisitFieldDecl(FieldDecl *D);
> - void VisitFunctionDecl(FunctionDecl *D);
> - void VisitNamedDecl(NamedDecl *D);
> - void VisitNamespaceDecl(NamespaceDecl *D);
> - void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
> - void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
> - void VisitClassTemplateDecl(ClassTemplateDecl *D);
> - void VisitObjCContainerDecl(ObjCContainerDecl *CD);
> - void VisitObjCMethodDecl(ObjCMethodDecl *MD);
> - void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
> - void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
> - void VisitTagDecl(TagDecl *D);
> - void VisitTypedefDecl(TypedefDecl *D);
> - void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
> - void VisitVarDecl(VarDecl *D);
> - void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
> - void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
> - void VisitLinkageSpecDecl(LinkageSpecDecl *D) {
> - IgnoreResults = true;
> - }
> - void VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
> - IgnoreResults = true;
> - }
> - void VisitUsingDecl(UsingDecl *D) {
> - IgnoreResults = true;
> - }
> - void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
> - IgnoreResults = true;
> - }
> - void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
> - IgnoreResults = true;
> - }
> -
> - /// Generate the string component containing the location of the
> - /// declaration.
> - bool GenLoc(const Decl *D);
> -
> - /// String generation methods used both by the visitation methods
> - /// and from other clients that want to directly generate USRs. These
> - /// methods do not construct complete USRs (which incorporate the parents
> - /// of an AST element), but only the fragments concerning the AST element
> - /// itself.
> -
> - /// Generate a USR for an Objective-C class.
> - void GenObjCClass(StringRef cls);
> - /// Generate a USR for an Objective-C class category.
> - void GenObjCCategory(StringRef cls, StringRef cat);
> - /// Generate a USR fragment for an Objective-C instance variable. The
> - /// complete USR can be created by concatenating the USR for the
> - /// encompassing class with this USR fragment.
> - void GenObjCIvar(StringRef ivar);
> - /// Generate a USR fragment for an Objective-C method.
> - void GenObjCMethod(StringRef sel, bool isInstanceMethod);
> - /// Generate a USR fragment for an Objective-C property.
> - void GenObjCProperty(StringRef prop);
> - /// Generate a USR for an Objective-C protocol.
> - void GenObjCProtocol(StringRef prot);
> -
> - void VisitType(QualType T);
> - void VisitTemplateParameterList(const TemplateParameterList *Params);
> - void VisitTemplateName(TemplateName Name);
> - void VisitTemplateArgument(const TemplateArgument &Arg);
> -
> - /// Emit a Decl's name using NamedDecl::printName() and return true if
> - /// the decl had no name.
> - bool EmitDeclName(const NamedDecl *D);
> -};
> -
> -} // end anonymous namespace
> -
> -//===----------------------------------------------------------------------===//
> -// Generating USRs from ASTS.
> -//===----------------------------------------------------------------------===//
> -
> -bool USRGenerator::EmitDeclName(const NamedDecl *D) {
> - Out.flush();
> - const unsigned startSize = Buf.size();
> - D->printName(Out);
> - Out.flush();
> - const unsigned endSize = Buf.size();
> - return startSize == endSize;
> -}
> -
> -static bool InAnonymousNamespace(const Decl *D) {
> - if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D->getDeclContext()))
> - return ND->isAnonymousNamespace();
> - return false;
> -}
> -
> -static inline bool ShouldGenerateLocation(const NamedDecl *D) {
> - return D->getLinkage() != ExternalLinkage && !InAnonymousNamespace(D);
> -}
> -
> -void USRGenerator::VisitDeclContext(DeclContext *DC) {
> - if (NamedDecl *D = dyn_cast<NamedDecl>(DC))
> - Visit(D);
> -}
> -
> -void USRGenerator::VisitFieldDecl(FieldDecl *D) {
> - // The USR for an ivar declared in a class extension is based on the
> - // ObjCInterfaceDecl, not the ObjCCategoryDecl.
> - if (ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
> - Visit(ID);
> - else
> - VisitDeclContext(D->getDeclContext());
> - Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");
> - if (EmitDeclName(D)) {
> - // Bit fields can be anonymous.
> - IgnoreResults = true;
> - return;
> - }
> -}
> -
> -void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {
> - if (ShouldGenerateLocation(D) && GenLoc(D))
> - return;
> -
> - VisitDeclContext(D->getDeclContext());
> - if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
> - Out << "@FT@";
> - VisitTemplateParameterList(FunTmpl->getTemplateParameters());
> - } else
> - Out << "@F@";
> - D->printName(Out);
> -
> - ASTContext &Ctx = *Context;
> - if (!Ctx.getLangOpts().CPlusPlus || D->isExternC())
> - return;
> -
> - if (const TemplateArgumentList *
> - SpecArgs = D->getTemplateSpecializationArgs()) {
> - Out << '<';
> - for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) {
> - Out << '#';
> - VisitTemplateArgument(SpecArgs->get(I));
> - }
> - Out << '>';
> - }
> -
> - // Mangle in type information for the arguments.
> - for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end();
> - I != E; ++I) {
> - Out << '#';
> - if (ParmVarDecl *PD = *I)
> - VisitType(PD->getType());
> - }
> - if (D->isVariadic())
> - Out << '.';
> - Out << '#';
> - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
> - if (MD->isStatic())
> - Out << 'S';
> - if (unsigned quals = MD->getTypeQualifiers())
> - Out << (char)('0' + quals);
> - }
> -}
> -
> -void USRGenerator::VisitNamedDecl(NamedDecl *D) {
> - VisitDeclContext(D->getDeclContext());
> - Out << "@";
> -
> - if (EmitDeclName(D)) {
> - // The string can be empty if the declaration has no name; e.g., it is
> - // the ParmDecl with no name for declaration of a function pointer type,
> - // e.g.: void (*f)(void *);
> - // In this case, don't generate a USR.
> - IgnoreResults = true;
> - }
> -}
> -
> -void USRGenerator::VisitVarDecl(VarDecl *D) {
> - // VarDecls can be declared 'extern' within a function or method body,
> - // but their enclosing DeclContext is the function, not the TU. We need
> - // to check the storage class to correctly generate the USR.
> - if (ShouldGenerateLocation(D) && GenLoc(D))
> - return;
> -
> - VisitDeclContext(D->getDeclContext());
> -
> - // Variables always have simple names.
> - StringRef s = D->getName();
> -
> - // The string can be empty if the declaration has no name; e.g., it is
> - // the ParmDecl with no name for declaration of a function pointer type, e.g.:
> - // void (*f)(void *);
> - // In this case, don't generate a USR.
> - if (s.empty())
> - IgnoreResults = true;
> - else
> - Out << '@' << s;
> -}
> -
> -void USRGenerator::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
> - GenLoc(D);
> - return;
> -}
> -
> -void USRGenerator::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
> - GenLoc(D);
> - return;
> -}
> -
> -void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
> - if (D->isAnonymousNamespace()) {
> - Out << "@aN";
> - return;
> - }
> -
> - VisitDeclContext(D->getDeclContext());
> - if (!IgnoreResults)
> - Out << "@N@" << D->getName();
> -}
> -
> -void USRGenerator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
> - VisitFunctionDecl(D->getTemplatedDecl());
> -}
> -
> -void USRGenerator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
> - VisitTagDecl(D->getTemplatedDecl());
> -}
> -
> -void USRGenerator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
> - VisitDeclContext(D->getDeclContext());
> - if (!IgnoreResults)
> - Out << "@NA@" << D->getName();
> -}
> -
> -void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
> - DeclContext *container = D->getDeclContext();
> - if (ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {
> - Visit(pd);
> - }
> - else {
> - // The USR for a method declared in a class extension or category is based on
> - // the ObjCInterfaceDecl, not the ObjCCategoryDecl.
> - ObjCInterfaceDecl *ID = D->getClassInterface();
> - if (!ID) {
> - IgnoreResults = true;
> - return;
> - }
> - Visit(ID);
> - }
> - // Ideally we would use 'GenObjCMethod', but this is such a hot path
> - // for Objective-C code that we don't want to use
> - // DeclarationName::getAsString().
> - Out << (D->isInstanceMethod() ? "(im)" : "(cm)");
> - DeclarationName N(D->getSelector());
> - N.printName(Out);
> -}
> -
> -void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
> - switch (D->getKind()) {
> - default:
> - llvm_unreachable("Invalid ObjC container.");
> - case Decl::ObjCInterface:
> - case Decl::ObjCImplementation:
> - GenObjCClass(D->getName());
> - break;
> - case Decl::ObjCCategory: {
> - ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
> - ObjCInterfaceDecl *ID = CD->getClassInterface();
> - if (!ID) {
> - // Handle invalid code where the @interface might not
> - // have been specified.
> - // FIXME: We should be able to generate this USR even if the
> - // @interface isn't available.
> - IgnoreResults = true;
> - return;
> - }
> - // Specially handle class extensions, which are anonymous categories.
> - // We want to mangle in the location to uniquely distinguish them.
> - if (CD->IsClassExtension()) {
> - Out << "objc(ext)" << ID->getName() << '@';
> - GenLoc(CD);
> - }
> - else
> - GenObjCCategory(ID->getName(), CD->getName());
> -
> - break;
> - }
> - case Decl::ObjCCategoryImpl: {
> - ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
> - ObjCInterfaceDecl *ID = CD->getClassInterface();
> - if (!ID) {
> - // Handle invalid code where the @interface might not
> - // have been specified.
> - // FIXME: We should be able to generate this USR even if the
> - // @interface isn't available.
> - IgnoreResults = true;
> - return;
> - }
> - GenObjCCategory(ID->getName(), CD->getName());
> - break;
> - }
> - case Decl::ObjCProtocol:
> - GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName());
> - break;
> - }
> -}
> -
> -void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
> - // The USR for a property declared in a class extension or category is based
> - // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
> - if (ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
> - Visit(ID);
> - else
> - Visit(cast<Decl>(D->getDeclContext()));
> - GenObjCProperty(D->getName());
> -}
> -
> -void USRGenerator::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
> - if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
> - VisitObjCPropertyDecl(PD);
> - return;
> - }
> -
> - IgnoreResults = true;
> -}
> -
> -void USRGenerator::VisitTagDecl(TagDecl *D) {
> - // Add the location of the tag decl to handle resolution across
> - // translation units.
> - if (ShouldGenerateLocation(D) && GenLoc(D))
> - return;
> -
> - D = D->getCanonicalDecl();
> - VisitDeclContext(D->getDeclContext());
> -
> - bool AlreadyStarted = false;
> - if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
> - if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
> - AlreadyStarted = true;
> -
> - switch (D->getTagKind()) {
> - case TTK_Struct: Out << "@ST"; break;
> - case TTK_Class: Out << "@CT"; break;
> - case TTK_Union: Out << "@UT"; break;
> - case TTK_Enum: llvm_unreachable("enum template");
> - }
> - VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
> - } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
> - = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
> - AlreadyStarted = true;
> -
> - switch (D->getTagKind()) {
> - case TTK_Struct: Out << "@SP"; break;
> - case TTK_Class: Out << "@CP"; break;
> - case TTK_Union: Out << "@UP"; break;
> - case TTK_Enum: llvm_unreachable("enum partial specialization");
> - }
> - VisitTemplateParameterList(PartialSpec->getTemplateParameters());
> - }
> - }
> -
> - if (!AlreadyStarted) {
> - switch (D->getTagKind()) {
> - case TTK_Struct: Out << "@S"; break;
> - case TTK_Class: Out << "@C"; break;
> - case TTK_Union: Out << "@U"; break;
> - case TTK_Enum: Out << "@E"; break;
> - }
> - }
> -
> - Out << '@';
> - Out.flush();
> - assert(Buf.size() > 0);
> - const unsigned off = Buf.size() - 1;
> -
> - if (EmitDeclName(D)) {
> - if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
> - Buf[off] = 'A';
> - Out << '@' << *TD;
> - }
> - else
> - Buf[off] = 'a';
> - }
> -
> - // For a class template specialization, mangle the template arguments.
> - if (ClassTemplateSpecializationDecl *Spec
> - = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
> - const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs();
> - Out << '>';
> - for (unsigned I = 0, N = Args.size(); I != N; ++I) {
> - Out << '#';
> - VisitTemplateArgument(Args.get(I));
> - }
> - }
> -}
> -
> -void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
> - if (ShouldGenerateLocation(D) && GenLoc(D))
> - return;
> - DeclContext *DC = D->getDeclContext();
> - if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
> - Visit(DCN);
> - Out << "@T@";
> - Out << D->getName();
> -}
> -
> -void USRGenerator::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
> - GenLoc(D);
> - return;
> -}
> -
> -bool USRGenerator::GenLoc(const Decl *D) {
> - if (generatedLoc)
> - return IgnoreResults;
> - generatedLoc = true;
> -
> - // Guard against null declarations in invalid code.
> - if (!D) {
> - IgnoreResults = true;
> - return true;
> - }
> -
> - // Use the location of canonical decl.
> - D = D->getCanonicalDecl();
> -
> - const SourceManager &SM = Context->getSourceManager();
> - SourceLocation L = D->getLocStart();
> - if (L.isInvalid()) {
> - IgnoreResults = true;
> - return true;
> - }
> - L = SM.getExpansionLoc(L);
> - const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(L);
> - const FileEntry *FE = SM.getFileEntryForID(Decomposed.first);
> - if (FE) {
> - Out << llvm::sys::path::filename(FE->getName());
> - }
> - else {
> - // This case really isn't interesting.
> - IgnoreResults = true;
> - return true;
> - }
> - // Use the offest into the FileID to represent the location. Using
> - // a line/column can cause us to look back at the original source file,
> - // which is expensive.
> - Out << '@' << Decomposed.second;
> - return IgnoreResults;
> -}
> -
> -void USRGenerator::VisitType(QualType T) {
> - // This method mangles in USR information for types. It can possibly
> - // just reuse the naming-mangling logic used by codegen, although the
> - // requirements for USRs might not be the same.
> - ASTContext &Ctx = *Context;
> -
> - do {
> - T = Ctx.getCanonicalType(T);
> - Qualifiers Q = T.getQualifiers();
> - unsigned qVal = 0;
> - if (Q.hasConst())
> - qVal |= 0x1;
> - if (Q.hasVolatile())
> - qVal |= 0x2;
> - if (Q.hasRestrict())
> - qVal |= 0x4;
> - if(qVal)
> - Out << ((char) ('0' + qVal));
> -
> - // Mangle in ObjC GC qualifiers?
> -
> - if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
> - Out << 'P';
> - T = Expansion->getPattern();
> - }
> -
> - if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
> - unsigned char c = '\0';
> - switch (BT->getKind()) {
> - case BuiltinType::Void:
> - c = 'v'; break;
> - case BuiltinType::Bool:
> - c = 'b'; break;
> - case BuiltinType::Char_U:
> - case BuiltinType::UChar:
> - c = 'c'; break;
> - case BuiltinType::Char16:
> - c = 'q'; break;
> - case BuiltinType::Char32:
> - c = 'w'; break;
> - case BuiltinType::UShort:
> - c = 's'; break;
> - case BuiltinType::UInt:
> - c = 'i'; break;
> - case BuiltinType::ULong:
> - c = 'l'; break;
> - case BuiltinType::ULongLong:
> - c = 'k'; break;
> - case BuiltinType::UInt128:
> - c = 'j'; break;
> - case BuiltinType::Char_S:
> - case BuiltinType::SChar:
> - c = 'C'; break;
> - case BuiltinType::WChar_S:
> - case BuiltinType::WChar_U:
> - c = 'W'; break;
> - case BuiltinType::Short:
> - c = 'S'; break;
> - case BuiltinType::Int:
> - c = 'I'; break;
> - case BuiltinType::Long:
> - c = 'L'; break;
> - case BuiltinType::LongLong:
> - c = 'K'; break;
> - case BuiltinType::Int128:
> - c = 'J'; break;
> - case BuiltinType::Half:
> - c = 'h'; break;
> - case BuiltinType::Float:
> - c = 'f'; break;
> - case BuiltinType::Double:
> - c = 'd'; break;
> - case BuiltinType::LongDouble:
> - c = 'D'; break;
> - case BuiltinType::NullPtr:
> - c = 'n'; break;
> -#define BUILTIN_TYPE(Id, SingletonId)
> -#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
> -#include "clang/AST/BuiltinTypes.def"
> - case BuiltinType::Dependent:
> - IgnoreResults = true;
> - return;
> - case BuiltinType::ObjCId:
> - c = 'o'; break;
> - case BuiltinType::ObjCClass:
> - c = 'O'; break;
> - case BuiltinType::ObjCSel:
> - c = 'e'; break;
> - }
> - Out << c;
> - return;
> - }
> -
> - // If we have already seen this (non-built-in) type, use a substitution
> - // encoding.
> - llvm::DenseMap<const Type *, unsigned>::iterator Substitution
> - = TypeSubstitutions.find(T.getTypePtr());
> - if (Substitution != TypeSubstitutions.end()) {
> - Out << 'S' << Substitution->second << '_';
> - return;
> - } else {
> - // Record this as a substitution.
> - unsigned Number = TypeSubstitutions.size();
> - TypeSubstitutions[T.getTypePtr()] = Number;
> - }
> -
> - if (const PointerType *PT = T->getAs<PointerType>()) {
> - Out << '*';
> - T = PT->getPointeeType();
> - continue;
> - }
> - if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
> - Out << '&';
> - T = RT->getPointeeType();
> - continue;
> - }
> - if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
> - Out << 'F';
> - VisitType(FT->getResultType());
> - for (FunctionProtoType::arg_type_iterator
> - I = FT->arg_type_begin(), E = FT->arg_type_end(); I!=E; ++I) {
> - VisitType(*I);
> - }
> - if (FT->isVariadic())
> - Out << '.';
> - return;
> - }
> - if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
> - Out << 'B';
> - T = BT->getPointeeType();
> - continue;
> - }
> - if (const ComplexType *CT = T->getAs<ComplexType>()) {
> - Out << '<';
> - T = CT->getElementType();
> - continue;
> - }
> - if (const TagType *TT = T->getAs<TagType>()) {
> - Out << '$';
> - VisitTagDecl(TT->getDecl());
> - return;
> - }
> - if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
> - Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
> - return;
> - }
> - if (const TemplateSpecializationType *Spec
> - = T->getAs<TemplateSpecializationType>()) {
> - Out << '>';
> - VisitTemplateName(Spec->getTemplateName());
> - Out << Spec->getNumArgs();
> - for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
> - VisitTemplateArgument(Spec->getArg(I));
> - return;
> - }
> -
> - // Unhandled type.
> - Out << ' ';
> - break;
> - } while (true);
> -}
> -
> -void USRGenerator::VisitTemplateParameterList(
> - const TemplateParameterList *Params) {
> - if (!Params)
> - return;
> - Out << '>' << Params->size();
> - for (TemplateParameterList::const_iterator P = Params->begin(),
> - PEnd = Params->end();
> - P != PEnd; ++P) {
> - Out << '#';
> - if (isa<TemplateTypeParmDecl>(*P)) {
> - if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
> - Out<< 'p';
> - Out << 'T';
> - continue;
> - }
> -
> - if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
> - if (NTTP->isParameterPack())
> - Out << 'p';
> - Out << 'N';
> - VisitType(NTTP->getType());
> - continue;
> - }
> -
> - TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
> - if (TTP->isParameterPack())
> - Out << 'p';
> - Out << 't';
> - VisitTemplateParameterList(TTP->getTemplateParameters());
> - }
> -}
> -
> -void USRGenerator::VisitTemplateName(TemplateName Name) {
> - if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
> - if (TemplateTemplateParmDecl *TTP
> - = dyn_cast<TemplateTemplateParmDecl>(Template)) {
> - Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
> - return;
> - }
> -
> - Visit(Template);
> - return;
> - }
> -
> - // FIXME: Visit dependent template names.
> -}
> -
> -void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
> - switch (Arg.getKind()) {
> - case TemplateArgument::Null:
> - break;
> -
> - case TemplateArgument::Declaration:
> - if (Decl *D = Arg.getAsDecl())
> - Visit(D);
> - break;
> -
> - case TemplateArgument::TemplateExpansion:
> - Out << 'P'; // pack expansion of...
> - // Fall through
> - case TemplateArgument::Template:
> - VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
> - break;
> -
> - case TemplateArgument::Expression:
> - // FIXME: Visit expressions.
> - break;
> -
> - case TemplateArgument::Pack:
> - Out << 'p' << Arg.pack_size();
> - for (TemplateArgument::pack_iterator P = Arg.pack_begin(), PEnd = Arg.pack_end();
> - P != PEnd; ++P)
> - VisitTemplateArgument(*P);
> - break;
> -
> - case TemplateArgument::Type:
> - VisitType(Arg.getAsType());
> - break;
> -
> - case TemplateArgument::Integral:
> - Out << 'V';
> - VisitType(Arg.getIntegralType());
> - Out << Arg.getAsIntegral();
> - break;
> - }
> -}
> -
> -//===----------------------------------------------------------------------===//
> -// General purpose USR generation methods.
> -//===----------------------------------------------------------------------===//
> -
> -void USRGenerator::GenObjCClass(StringRef cls) {
> - Out << "objc(cs)" << cls;
> -}
> -
> -void USRGenerator::GenObjCCategory(StringRef cls, StringRef cat) {
> - Out << "objc(cy)" << cls << '@' << cat;
> -}
> -
> -void USRGenerator::GenObjCIvar(StringRef ivar) {
> - Out << '@' << ivar;
> -}
> -
> -void USRGenerator::GenObjCMethod(StringRef meth, bool isInstanceMethod) {
> - Out << (isInstanceMethod ? "(im)" : "(cm)") << meth;
> -}
> -
> -void USRGenerator::GenObjCProperty(StringRef prop) {
> - Out << "(py)" << prop;
> -}
> -
> -void USRGenerator::GenObjCProtocol(StringRef prot) {
> - Out << "objc(pl)" << prot;
> -}
> -
> -//===----------------------------------------------------------------------===//
> -// API hooks.
> -//===----------------------------------------------------------------------===//
> -
> -static inline StringRef extractUSRSuffix(StringRef s) {
> - return s.startswith("c:") ? s.substr(2) : "";
> -}
> -
> -bool cxcursor::getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf) {
> - // Don't generate USRs for things with invalid locations.
> - if (!D || D->getLocStart().isInvalid())
> - return true;
> -
> - // Check if the cursor has 'NoLinkage'.
> - if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
> - switch (ND->getLinkage()) {
> - case ExternalLinkage:
> - // Generate USRs for all entities with external linkage.
> - break;
> - case NoLinkage:
> - case UniqueExternalLinkage:
> - // We allow enums, typedefs, and structs that have no linkage to
> - // have USRs that are anchored to the file they were defined in
> - // (e.g., the header). This is a little gross, but in principal
> - // enums/anonymous structs/etc. defined in a common header file
> - // are referred to across multiple translation units.
> - if (isa<TagDecl>(ND) || isa<TypedefDecl>(ND) ||
> - isa<EnumConstantDecl>(ND) || isa<FieldDecl>(ND) ||
> - isa<VarDecl>(ND) || isa<NamespaceDecl>(ND))
> - break;
> - // Fall-through.
> - case InternalLinkage:
> - if (isa<FunctionDecl>(ND))
> - break;
> - }
> -
> - {
> - USRGenerator UG(&D->getASTContext(), &Buf);
> - UG->Visit(const_cast<Decl*>(D));
> -
> - if (UG->ignoreResults())
> - return true;
> - }
> -
> - return false;
> -}
> -
> -extern "C" {
> -
> -CXString clang_getCursorUSR(CXCursor C) {
> - const CXCursorKind &K = clang_getCursorKind(C);
> -
> - if (clang_isDeclaration(K)) {
> - Decl *D = cxcursor::getCursorDecl(C);
> - if (!D)
> - return createCXString("");
> -
> - CXTranslationUnit TU = cxcursor::getCursorTU(C);
> - if (!TU)
> - return createCXString("");
> -
> - CXStringBuf *buf = cxstring::getCXStringBuf(TU);
> - if (!buf)
> - return createCXString("");
> -
> - bool Ignore = cxcursor::getDeclCursorUSR(D, buf->Data);
> - if (Ignore) {
> - disposeCXStringBuf(buf);
> - return createCXString("");
> - }
> -
> - // Return the C-string, but don't make a copy since it is already in
> - // the string buffer.
> - buf->Data.push_back('\0');
> - return createCXString(buf);
> - }
> -
> - if (K == CXCursor_MacroDefinition) {
> - CXTranslationUnit TU = cxcursor::getCursorTU(C);
> - if (!TU)
> - return createCXString("");
> -
> - CXStringBuf *buf = cxstring::getCXStringBuf(TU);
> - if (!buf)
> - return createCXString("");
> -
> - {
> - USRGenerator UG(&cxcursor::getCursorASTUnit(C)->getASTContext(),
> - &buf->Data);
> - UG << "macro@"
> - << cxcursor::getCursorMacroDefinition(C)->getName()->getNameStart();
> - }
> - buf->Data.push_back('\0');
> - return createCXString(buf);
> - }
> -
> - return createCXString("");
> -}
> -
> -CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) {
> - USRGenerator UG;
> - UG << extractUSRSuffix(clang_getCString(classUSR));
> - UG->GenObjCIvar(name);
> - return createCXString(UG.str(), true);
> -}
> -
> -CXString clang_constructUSR_ObjCMethod(const char *name,
> - unsigned isInstanceMethod,
> - CXString classUSR) {
> - USRGenerator UG;
> - UG << extractUSRSuffix(clang_getCString(classUSR));
> - UG->GenObjCMethod(name, isInstanceMethod);
> - return createCXString(UG.str(), true);
> -}
> -
> -CXString clang_constructUSR_ObjCClass(const char *name) {
> - USRGenerator UG;
> - UG->GenObjCClass(name);
> - return createCXString(UG.str(), true);
> -}
> -
> -CXString clang_constructUSR_ObjCProtocol(const char *name) {
> - USRGenerator UG;
> - UG->GenObjCProtocol(name);
> - return createCXString(UG.str(), true);
> -}
> -
> -CXString clang_constructUSR_ObjCCategory(const char *class_name,
> - const char *category_name) {
> - USRGenerator UG;
> - UG->GenObjCCategory(class_name, category_name);
> - return createCXString(UG.str(), true);
> -}
> -
> -CXString clang_constructUSR_ObjCProperty(const char *property,
> - CXString classUSR) {
> - USRGenerator UG;
> - UG << extractUSRSuffix(clang_getCString(classUSR));
> - UG->GenObjCProperty(property);
> - return createCXString(UG.str(), true);
> -}
> -
> -} // end extern "C"
> +//===- CIndexUSR.cpp - Clang-C Source Indexing Library --------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file implements the generation and use of USRs from CXEntities.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "CIndexer.h"
> +#include "CXCursor.h"
> +#include "CXString.h"
> +#include "clang/AST/DeclTemplate.h"
> +#include "clang/AST/DeclVisitor.h"
> +#include "clang/Frontend/ASTUnit.h"
> +#include "clang/Lex/PreprocessingRecord.h"
> +#include "llvm/ADT/SmallString.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +using namespace clang;
> +using namespace clang::cxstring;
> +
> +//===----------------------------------------------------------------------===//
> +// USR generation.
> +//===----------------------------------------------------------------------===//
> +
> +namespace {
> +class USRGenerator : public DeclVisitor<USRGenerator> {
> + OwningPtr<SmallString<128> > OwnedBuf;
> + SmallVectorImpl<char> &Buf;
> + llvm::raw_svector_ostream Out;
> + bool IgnoreResults;
> + ASTContext *Context;
> + bool generatedLoc;
> +
> + llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
> +
> +public:
> + explicit USRGenerator(ASTContext *Ctx = 0, SmallVectorImpl<char> *extBuf = 0)
> + : OwnedBuf(extBuf ? 0 : new SmallString<128>()),
> + Buf(extBuf ? *extBuf : *OwnedBuf.get()),
> + Out(Buf),
> + IgnoreResults(false),
> + Context(Ctx),
> + generatedLoc(false)
> + {
> + // Add the USR space prefix.
> + Out << "c:";
> + }
> +
> + StringRef str() {
> + return Out.str();
> + }
> +
> + USRGenerator* operator->() { return this; }
> +
> + template <typename T>
> + llvm::raw_svector_ostream &operator<<(const T &x) {
> + Out << x;
> + return Out;
> + }
> +
> + bool ignoreResults() const { return IgnoreResults; }
> +
> + // Visitation methods from generating USRs from AST elements.
> + void VisitDeclContext(DeclContext *D);
> + void VisitFieldDecl(FieldDecl *D);
> + void VisitFunctionDecl(FunctionDecl *D);
> + void VisitNamedDecl(NamedDecl *D);
> + void VisitNamespaceDecl(NamespaceDecl *D);
> + void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
> + void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
> + void VisitClassTemplateDecl(ClassTemplateDecl *D);
> + void VisitObjCContainerDecl(ObjCContainerDecl *CD);
> + void VisitObjCMethodDecl(ObjCMethodDecl *MD);
> + void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
> + void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
> + void VisitTagDecl(TagDecl *D);
> + void VisitTypedefDecl(TypedefDecl *D);
> + void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
> + void VisitVarDecl(VarDecl *D);
> + void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
> + void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
> + void VisitLinkageSpecDecl(LinkageSpecDecl *D) {
> + IgnoreResults = true;
> + }
> + void VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
> + IgnoreResults = true;
> + }
> + void VisitUsingDecl(UsingDecl *D) {
> + IgnoreResults = true;
> + }
> + void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
> + IgnoreResults = true;
> + }
> + void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
> + IgnoreResults = true;
> + }
> +
> + /// Generate the string component containing the location of the
> + /// declaration.
> + bool GenLoc(const Decl *D);
> +
> + /// String generation methods used both by the visitation methods
> + /// and from other clients that want to directly generate USRs. These
> + /// methods do not construct complete USRs (which incorporate the parents
> + /// of an AST element), but only the fragments concerning the AST element
> + /// itself.
> +
> + /// Generate a USR for an Objective-C class.
> + void GenObjCClass(StringRef cls);
> + /// Generate a USR for an Objective-C class category.
> + void GenObjCCategory(StringRef cls, StringRef cat);
> + /// Generate a USR fragment for an Objective-C instance variable. The
> + /// complete USR can be created by concatenating the USR for the
> + /// encompassing class with this USR fragment.
> + void GenObjCIvar(StringRef ivar);
> + /// Generate a USR fragment for an Objective-C method.
> + void GenObjCMethod(StringRef sel, bool isInstanceMethod);
> + /// Generate a USR fragment for an Objective-C property.
> + void GenObjCProperty(StringRef prop);
> + /// Generate a USR for an Objective-C protocol.
> + void GenObjCProtocol(StringRef prot);
> +
> + void VisitType(QualType T);
> + void VisitTemplateParameterList(const TemplateParameterList *Params);
> + void VisitTemplateName(TemplateName Name);
> + void VisitTemplateArgument(const TemplateArgument &Arg);
> +
> + /// Emit a Decl's name using NamedDecl::printName() and return true if
> + /// the decl had no name.
> + bool EmitDeclName(const NamedDecl *D);
> +};
> +
> +} // end anonymous namespace
> +
> +//===----------------------------------------------------------------------===//
> +// Generating USRs from ASTS.
> +//===----------------------------------------------------------------------===//
> +
> +bool USRGenerator::EmitDeclName(const NamedDecl *D) {
> + Out.flush();
> + const unsigned startSize = Buf.size();
> + D->printName(Out);
> + Out.flush();
> + const unsigned endSize = Buf.size();
> + return startSize == endSize;
> +}
> +
> +static bool InAnonymousNamespace(const Decl *D) {
> + if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D->getDeclContext()))
> + return ND->isAnonymousNamespace();
> + return false;
> +}
> +
> +static inline bool ShouldGenerateLocation(const NamedDecl *D) {
> + return D->getLinkage() != ExternalLinkage && !InAnonymousNamespace(D);
> +}
> +
> +void USRGenerator::VisitDeclContext(DeclContext *DC) {
> + if (NamedDecl *D = dyn_cast<NamedDecl>(DC))
> + Visit(D);
> +}
> +
> +void USRGenerator::VisitFieldDecl(FieldDecl *D) {
> + // The USR for an ivar declared in a class extension is based on the
> + // ObjCInterfaceDecl, not the ObjCCategoryDecl.
> + if (ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
> + Visit(ID);
> + else
> + VisitDeclContext(D->getDeclContext());
> + Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");
> + if (EmitDeclName(D)) {
> + // Bit fields can be anonymous.
> + IgnoreResults = true;
> + return;
> + }
> +}
> +
> +void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {
> + if (ShouldGenerateLocation(D) && GenLoc(D))
> + return;
> +
> + VisitDeclContext(D->getDeclContext());
> + if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
> + Out << "@FT@";
> + VisitTemplateParameterList(FunTmpl->getTemplateParameters());
> + } else
> + Out << "@F@";
> + D->printName(Out);
> +
> + ASTContext &Ctx = *Context;
> + if (!Ctx.getLangOpts().CPlusPlus || D->isExternC())
> + return;
> +
> + if (const TemplateArgumentList *
> + SpecArgs = D->getTemplateSpecializationArgs()) {
> + Out << '<';
> + for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) {
> + Out << '#';
> + VisitTemplateArgument(SpecArgs->get(I));
> + }
> + Out << '>';
> + }
> +
> + // Mangle in type information for the arguments.
> + for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end();
> + I != E; ++I) {
> + Out << '#';
> + if (ParmVarDecl *PD = *I)
> + VisitType(PD->getType());
> + }
> + if (D->isVariadic())
> + Out << '.';
> + Out << '#';
> + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
> + if (MD->isStatic())
> + Out << 'S';
> + if (unsigned quals = MD->getTypeQualifiers())
> + Out << (char)('0' + quals);
> + }
> +}
> +
> +void USRGenerator::VisitNamedDecl(NamedDecl *D) {
> + VisitDeclContext(D->getDeclContext());
> + Out << "@";
> +
> + if (EmitDeclName(D)) {
> + // The string can be empty if the declaration has no name; e.g., it is
> + // the ParmDecl with no name for declaration of a function pointer type,
> + // e.g.: void (*f)(void *);
> + // In this case, don't generate a USR.
> + IgnoreResults = true;
> + }
> +}
> +
> +void USRGenerator::VisitVarDecl(VarDecl *D) {
> + // VarDecls can be declared 'extern' within a function or method body,
> + // but their enclosing DeclContext is the function, not the TU. We need
> + // to check the storage class to correctly generate the USR.
> + if (ShouldGenerateLocation(D) && GenLoc(D))
> + return;
> +
> + VisitDeclContext(D->getDeclContext());
> +
> + // Variables always have simple names.
> + StringRef s = D->getName();
> +
> + // The string can be empty if the declaration has no name; e.g., it is
> + // the ParmDecl with no name for declaration of a function pointer type, e.g.:
> + // void (*f)(void *);
> + // In this case, don't generate a USR.
> + if (s.empty())
> + IgnoreResults = true;
> + else
> + Out << '@' << s;
> +}
> +
> +void USRGenerator::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
> + GenLoc(D);
> + return;
> +}
> +
> +void USRGenerator::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
> + GenLoc(D);
> + return;
> +}
> +
> +void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
> + if (D->isAnonymousNamespace()) {
> + Out << "@aN";
> + return;
> + }
> +
> + VisitDeclContext(D->getDeclContext());
> + if (!IgnoreResults)
> + Out << "@N@" << D->getName();
> +}
> +
> +void USRGenerator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
> + VisitFunctionDecl(D->getTemplatedDecl());
> +}
> +
> +void USRGenerator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
> + VisitTagDecl(D->getTemplatedDecl());
> +}
> +
> +void USRGenerator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
> + VisitDeclContext(D->getDeclContext());
> + if (!IgnoreResults)
> + Out << "@NA@" << D->getName();
> +}
> +
> +void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
> + DeclContext *container = D->getDeclContext();
> + if (ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {
> + Visit(pd);
> + }
> + else {
> + // The USR for a method declared in a class extension or category is based on
> + // the ObjCInterfaceDecl, not the ObjCCategoryDecl.
> + ObjCInterfaceDecl *ID = D->getClassInterface();
> + if (!ID) {
> + IgnoreResults = true;
> + return;
> + }
> + Visit(ID);
> + }
> + // Ideally we would use 'GenObjCMethod', but this is such a hot path
> + // for Objective-C code that we don't want to use
> + // DeclarationName::getAsString().
> + Out << (D->isInstanceMethod() ? "(im)" : "(cm)");
> + DeclarationName N(D->getSelector());
> + N.printName(Out);
> +}
> +
> +void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
> + switch (D->getKind()) {
> + default:
> + llvm_unreachable("Invalid ObjC container.");
> + case Decl::ObjCInterface:
> + case Decl::ObjCImplementation:
> + GenObjCClass(D->getName());
> + break;
> + case Decl::ObjCCategory: {
> + ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
> + ObjCInterfaceDecl *ID = CD->getClassInterface();
> + if (!ID) {
> + // Handle invalid code where the @interface might not
> + // have been specified.
> + // FIXME: We should be able to generate this USR even if the
> + // @interface isn't available.
> + IgnoreResults = true;
> + return;
> + }
> + // Specially handle class extensions, which are anonymous categories.
> + // We want to mangle in the location to uniquely distinguish them.
> + if (CD->IsClassExtension()) {
> + Out << "objc(ext)" << ID->getName() << '@';
> + GenLoc(CD);
> + }
> + else
> + GenObjCCategory(ID->getName(), CD->getName());
> +
> + break;
> + }
> + case Decl::ObjCCategoryImpl: {
> + ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
> + ObjCInterfaceDecl *ID = CD->getClassInterface();
> + if (!ID) {
> + // Handle invalid code where the @interface might not
> + // have been specified.
> + // FIXME: We should be able to generate this USR even if the
> + // @interface isn't available.
> + IgnoreResults = true;
> + return;
> + }
> + GenObjCCategory(ID->getName(), CD->getName());
> + break;
> + }
> + case Decl::ObjCProtocol:
> + GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName());
> + break;
> + }
> +}
> +
> +void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
> + // The USR for a property declared in a class extension or category is based
> + // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
> + if (ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
> + Visit(ID);
> + else
> + Visit(cast<Decl>(D->getDeclContext()));
> + GenObjCProperty(D->getName());
> +}
> +
> +void USRGenerator::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
> + if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
> + VisitObjCPropertyDecl(PD);
> + return;
> + }
> +
> + IgnoreResults = true;
> +}
> +
> +void USRGenerator::VisitTagDecl(TagDecl *D) {
> + // Add the location of the tag decl to handle resolution across
> + // translation units.
> + if (ShouldGenerateLocation(D) && GenLoc(D))
> + return;
> +
> + D = D->getCanonicalDecl();
> + VisitDeclContext(D->getDeclContext());
> +
> + bool AlreadyStarted = false;
> + if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
> + if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
> + AlreadyStarted = true;
> +
> + switch (D->getTagKind()) {
> + case TTK_Interface:
> + case TTK_Struct: Out << "@ST"; break;
> + case TTK_Class: Out << "@CT"; break;
> + case TTK_Union: Out << "@UT"; break;
> + case TTK_Enum: llvm_unreachable("enum template");
> + }
> + VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
> + } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
> + = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
> + AlreadyStarted = true;
> +
> + switch (D->getTagKind()) {
> + case TTK_Interface:
> + case TTK_Struct: Out << "@SP"; break;
> + case TTK_Class: Out << "@CP"; break;
> + case TTK_Union: Out << "@UP"; break;
> + case TTK_Enum: llvm_unreachable("enum partial specialization");
> + }
> + VisitTemplateParameterList(PartialSpec->getTemplateParameters());
> + }
> + }
> +
> + if (!AlreadyStarted) {
> + switch (D->getTagKind()) {
> + case TTK_Interface:
> + case TTK_Struct: Out << "@S"; break;
> + case TTK_Class: Out << "@C"; break;
> + case TTK_Union: Out << "@U"; break;
> + case TTK_Enum: Out << "@E"; break;
> + }
> + }
> +
> + Out << '@';
> + Out.flush();
> + assert(Buf.size() > 0);
> + const unsigned off = Buf.size() - 1;
> +
> + if (EmitDeclName(D)) {
> + if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
> + Buf[off] = 'A';
> + Out << '@' << *TD;
> + }
> + else
> + Buf[off] = 'a';
> + }
> +
> + // For a class template specialization, mangle the template arguments.
> + if (ClassTemplateSpecializationDecl *Spec
> + = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
> + const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs();
> + Out << '>';
> + for (unsigned I = 0, N = Args.size(); I != N; ++I) {
> + Out << '#';
> + VisitTemplateArgument(Args.get(I));
> + }
> + }
> +}
> +
> +void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
> + if (ShouldGenerateLocation(D) && GenLoc(D))
> + return;
> + DeclContext *DC = D->getDeclContext();
> + if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
> + Visit(DCN);
> + Out << "@T@";
> + Out << D->getName();
> +}
> +
> +void USRGenerator::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
> + GenLoc(D);
> + return;
> +}
> +
> +bool USRGenerator::GenLoc(const Decl *D) {
> + if (generatedLoc)
> + return IgnoreResults;
> + generatedLoc = true;
> +
> + // Guard against null declarations in invalid code.
> + if (!D) {
> + IgnoreResults = true;
> + return true;
> + }
> +
> + // Use the location of canonical decl.
> + D = D->getCanonicalDecl();
> +
> + const SourceManager &SM = Context->getSourceManager();
> + SourceLocation L = D->getLocStart();
> + if (L.isInvalid()) {
> + IgnoreResults = true;
> + return true;
> + }
> + L = SM.getExpansionLoc(L);
> + const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(L);
> + const FileEntry *FE = SM.getFileEntryForID(Decomposed.first);
> + if (FE) {
> + Out << llvm::sys::path::filename(FE->getName());
> + }
> + else {
> + // This case really isn't interesting.
> + IgnoreResults = true;
> + return true;
> + }
> + // Use the offest into the FileID to represent the location. Using
> + // a line/column can cause us to look back at the original source file,
> + // which is expensive.
> + Out << '@' << Decomposed.second;
> + return IgnoreResults;
> +}
> +
> +void USRGenerator::VisitType(QualType T) {
> + // This method mangles in USR information for types. It can possibly
> + // just reuse the naming-mangling logic used by codegen, although the
> + // requirements for USRs might not be the same.
> + ASTContext &Ctx = *Context;
> +
> + do {
> + T = Ctx.getCanonicalType(T);
> + Qualifiers Q = T.getQualifiers();
> + unsigned qVal = 0;
> + if (Q.hasConst())
> + qVal |= 0x1;
> + if (Q.hasVolatile())
> + qVal |= 0x2;
> + if (Q.hasRestrict())
> + qVal |= 0x4;
> + if(qVal)
> + Out << ((char) ('0' + qVal));
> +
> + // Mangle in ObjC GC qualifiers?
> +
> + if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
> + Out << 'P';
> + T = Expansion->getPattern();
> + }
> +
> + if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
> + unsigned char c = '\0';
> + switch (BT->getKind()) {
> + case BuiltinType::Void:
> + c = 'v'; break;
> + case BuiltinType::Bool:
> + c = 'b'; break;
> + case BuiltinType::Char_U:
> + case BuiltinType::UChar:
> + c = 'c'; break;
> + case BuiltinType::Char16:
> + c = 'q'; break;
> + case BuiltinType::Char32:
> + c = 'w'; break;
> + case BuiltinType::UShort:
> + c = 's'; break;
> + case BuiltinType::UInt:
> + c = 'i'; break;
> + case BuiltinType::ULong:
> + c = 'l'; break;
> + case BuiltinType::ULongLong:
> + c = 'k'; break;
> + case BuiltinType::UInt128:
> + c = 'j'; break;
> + case BuiltinType::Char_S:
> + case BuiltinType::SChar:
> + c = 'C'; break;
> + case BuiltinType::WChar_S:
> + case BuiltinType::WChar_U:
> + c = 'W'; break;
> + case BuiltinType::Short:
> + c = 'S'; break;
> + case BuiltinType::Int:
> + c = 'I'; break;
> + case BuiltinType::Long:
> + c = 'L'; break;
> + case BuiltinType::LongLong:
> + c = 'K'; break;
> + case BuiltinType::Int128:
> + c = 'J'; break;
> + case BuiltinType::Half:
> + c = 'h'; break;
> + case BuiltinType::Float:
> + c = 'f'; break;
> + case BuiltinType::Double:
> + c = 'd'; break;
> + case BuiltinType::LongDouble:
> + c = 'D'; break;
> + case BuiltinType::NullPtr:
> + c = 'n'; break;
> +#define BUILTIN_TYPE(Id, SingletonId)
> +#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
> +#include "clang/AST/BuiltinTypes.def"
> + case BuiltinType::Dependent:
> + IgnoreResults = true;
> + return;
> + case BuiltinType::ObjCId:
> + c = 'o'; break;
> + case BuiltinType::ObjCClass:
> + c = 'O'; break;
> + case BuiltinType::ObjCSel:
> + c = 'e'; break;
> + }
> + Out << c;
> + return;
> + }
> +
> + // If we have already seen this (non-built-in) type, use a substitution
> + // encoding.
> + llvm::DenseMap<const Type *, unsigned>::iterator Substitution
> + = TypeSubstitutions.find(T.getTypePtr());
> + if (Substitution != TypeSubstitutions.end()) {
> + Out << 'S' << Substitution->second << '_';
> + return;
> + } else {
> + // Record this as a substitution.
> + unsigned Number = TypeSubstitutions.size();
> + TypeSubstitutions[T.getTypePtr()] = Number;
> + }
> +
> + if (const PointerType *PT = T->getAs<PointerType>()) {
> + Out << '*';
> + T = PT->getPointeeType();
> + continue;
> + }
> + if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
> + Out << '&';
> + T = RT->getPointeeType();
> + continue;
> + }
> + if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
> + Out << 'F';
> + VisitType(FT->getResultType());
> + for (FunctionProtoType::arg_type_iterator
> + I = FT->arg_type_begin(), E = FT->arg_type_end(); I!=E; ++I) {
> + VisitType(*I);
> + }
> + if (FT->isVariadic())
> + Out << '.';
> + return;
> + }
> + if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
> + Out << 'B';
> + T = BT->getPointeeType();
> + continue;
> + }
> + if (const ComplexType *CT = T->getAs<ComplexType>()) {
> + Out << '<';
> + T = CT->getElementType();
> + continue;
> + }
> + if (const TagType *TT = T->getAs<TagType>()) {
> + Out << '$';
> + VisitTagDecl(TT->getDecl());
> + return;
> + }
> + if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
> + Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
> + return;
> + }
> + if (const TemplateSpecializationType *Spec
> + = T->getAs<TemplateSpecializationType>()) {
> + Out << '>';
> + VisitTemplateName(Spec->getTemplateName());
> + Out << Spec->getNumArgs();
> + for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
> + VisitTemplateArgument(Spec->getArg(I));
> + return;
> + }
> +
> + // Unhandled type.
> + Out << ' ';
> + break;
> + } while (true);
> +}
> +
> +void USRGenerator::VisitTemplateParameterList(
> + const TemplateParameterList *Params) {
> + if (!Params)
> + return;
> + Out << '>' << Params->size();
> + for (TemplateParameterList::const_iterator P = Params->begin(),
> + PEnd = Params->end();
> + P != PEnd; ++P) {
> + Out << '#';
> + if (isa<TemplateTypeParmDecl>(*P)) {
> + if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
> + Out<< 'p';
> + Out << 'T';
> + continue;
> + }
> +
> + if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
> + if (NTTP->isParameterPack())
> + Out << 'p';
> + Out << 'N';
> + VisitType(NTTP->getType());
> + continue;
> + }
> +
> + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
> + if (TTP->isParameterPack())
> + Out << 'p';
> + Out << 't';
> + VisitTemplateParameterList(TTP->getTemplateParameters());
> + }
> +}
> +
> +void USRGenerator::VisitTemplateName(TemplateName Name) {
> + if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
> + if (TemplateTemplateParmDecl *TTP
> + = dyn_cast<TemplateTemplateParmDecl>(Template)) {
> + Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
> + return;
> + }
> +
> + Visit(Template);
> + return;
> + }
> +
> + // FIXME: Visit dependent template names.
> +}
> +
> +void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
> + switch (Arg.getKind()) {
> + case TemplateArgument::Null:
> + break;
> +
> + case TemplateArgument::Declaration:
> + if (Decl *D = Arg.getAsDecl())
> + Visit(D);
> + break;
> +
> + case TemplateArgument::TemplateExpansion:
> + Out << 'P'; // pack expansion of...
> + // Fall through
> + case TemplateArgument::Template:
> + VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
> + break;
> +
> + case TemplateArgument::Expression:
> + // FIXME: Visit expressions.
> + break;
> +
> + case TemplateArgument::Pack:
> + Out << 'p' << Arg.pack_size();
> + for (TemplateArgument::pack_iterator P = Arg.pack_begin(), PEnd = Arg.pack_end();
> + P != PEnd; ++P)
> + VisitTemplateArgument(*P);
> + break;
> +
> + case TemplateArgument::Type:
> + VisitType(Arg.getAsType());
> + break;
> +
> + case TemplateArgument::Integral:
> + Out << 'V';
> + VisitType(Arg.getIntegralType());
> + Out << Arg.getAsIntegral();
> + break;
> + }
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// General purpose USR generation methods.
> +//===----------------------------------------------------------------------===//
> +
> +void USRGenerator::GenObjCClass(StringRef cls) {
> + Out << "objc(cs)" << cls;
> +}
> +
> +void USRGenerator::GenObjCCategory(StringRef cls, StringRef cat) {
> + Out << "objc(cy)" << cls << '@' << cat;
> +}
> +
> +void USRGenerator::GenObjCIvar(StringRef ivar) {
> + Out << '@' << ivar;
> +}
> +
> +void USRGenerator::GenObjCMethod(StringRef meth, bool isInstanceMethod) {
> + Out << (isInstanceMethod ? "(im)" : "(cm)") << meth;
> +}
> +
> +void USRGenerator::GenObjCProperty(StringRef prop) {
> + Out << "(py)" << prop;
> +}
> +
> +void USRGenerator::GenObjCProtocol(StringRef prot) {
> + Out << "objc(pl)" << prot;
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// API hooks.
> +//===----------------------------------------------------------------------===//
> +
> +static inline StringRef extractUSRSuffix(StringRef s) {
> + return s.startswith("c:") ? s.substr(2) : "";
> +}
> +
> +bool cxcursor::getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf) {
> + // Don't generate USRs for things with invalid locations.
> + if (!D || D->getLocStart().isInvalid())
> + return true;
> +
> + // Check if the cursor has 'NoLinkage'.
> + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
> + switch (ND->getLinkage()) {
> + case ExternalLinkage:
> + // Generate USRs for all entities with external linkage.
> + break;
> + case NoLinkage:
> + case UniqueExternalLinkage:
> + // We allow enums, typedefs, and structs that have no linkage to
> + // have USRs that are anchored to the file they were defined in
> + // (e.g., the header). This is a little gross, but in principal
> + // enums/anonymous structs/etc. defined in a common header file
> + // are referred to across multiple translation units.
> + if (isa<TagDecl>(ND) || isa<TypedefDecl>(ND) ||
> + isa<EnumConstantDecl>(ND) || isa<FieldDecl>(ND) ||
> + isa<VarDecl>(ND) || isa<NamespaceDecl>(ND))
> + break;
> + // Fall-through.
> + case InternalLinkage:
> + if (isa<FunctionDecl>(ND))
> + break;
> + }
> +
> + {
> + USRGenerator UG(&D->getASTContext(), &Buf);
> + UG->Visit(const_cast<Decl*>(D));
> +
> + if (UG->ignoreResults())
> + return true;
> + }
> +
> + return false;
> +}
> +
> +extern "C" {
> +
> +CXString clang_getCursorUSR(CXCursor C) {
> + const CXCursorKind &K = clang_getCursorKind(C);
> +
> + if (clang_isDeclaration(K)) {
> + Decl *D = cxcursor::getCursorDecl(C);
> + if (!D)
> + return createCXString("");
> +
> + CXTranslationUnit TU = cxcursor::getCursorTU(C);
> + if (!TU)
> + return createCXString("");
> +
> + CXStringBuf *buf = cxstring::getCXStringBuf(TU);
> + if (!buf)
> + return createCXString("");
> +
> + bool Ignore = cxcursor::getDeclCursorUSR(D, buf->Data);
> + if (Ignore) {
> + disposeCXStringBuf(buf);
> + return createCXString("");
> + }
> +
> + // Return the C-string, but don't make a copy since it is already in
> + // the string buffer.
> + buf->Data.push_back('\0');
> + return createCXString(buf);
> + }
> +
> + if (K == CXCursor_MacroDefinition) {
> + CXTranslationUnit TU = cxcursor::getCursorTU(C);
> + if (!TU)
> + return createCXString("");
> +
> + CXStringBuf *buf = cxstring::getCXStringBuf(TU);
> + if (!buf)
> + return createCXString("");
> +
> + {
> + USRGenerator UG(&cxcursor::getCursorASTUnit(C)->getASTContext(),
> + &buf->Data);
> + UG << "macro@"
> + << cxcursor::getCursorMacroDefinition(C)->getName()->getNameStart();
> + }
> + buf->Data.push_back('\0');
> + return createCXString(buf);
> + }
> +
> + return createCXString("");
> +}
> +
> +CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) {
> + USRGenerator UG;
> + UG << extractUSRSuffix(clang_getCString(classUSR));
> + UG->GenObjCIvar(name);
> + return createCXString(UG.str(), true);
> +}
> +
> +CXString clang_constructUSR_ObjCMethod(const char *name,
> + unsigned isInstanceMethod,
> + CXString classUSR) {
> + USRGenerator UG;
> + UG << extractUSRSuffix(clang_getCString(classUSR));
> + UG->GenObjCMethod(name, isInstanceMethod);
> + return createCXString(UG.str(), true);
> +}
> +
> +CXString clang_constructUSR_ObjCClass(const char *name) {
> + USRGenerator UG;
> + UG->GenObjCClass(name);
> + return createCXString(UG.str(), true);
> +}
> +
> +CXString clang_constructUSR_ObjCProtocol(const char *name) {
> + USRGenerator UG;
> + UG->GenObjCProtocol(name);
> + return createCXString(UG.str(), true);
> +}
> +
> +CXString clang_constructUSR_ObjCCategory(const char *class_name,
> + const char *category_name) {
> + USRGenerator UG;
> + UG->GenObjCCategory(class_name, category_name);
> + return createCXString(UG.str(), true);
> +}
> +
> +CXString clang_constructUSR_ObjCProperty(const char *property,
> + CXString classUSR) {
> + USRGenerator UG;
> + UG << extractUSRSuffix(clang_getCString(classUSR));
> + UG->GenObjCProperty(property);
> + return createCXString(UG.str(), true);
> +}
> +
> +} // end extern "C"
>
> Modified: cfe/trunk/tools/libclang/IndexingContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexingContext.cpp?rev=163013&r1=163012&r2=163013&view=diff
> ==============================================================================
> --- cfe/trunk/tools/libclang/IndexingContext.cpp (original)
> +++ cfe/trunk/tools/libclang/IndexingContext.cpp Fri Aug 31 13:45:21 2012
> @@ -852,12 +852,16 @@
> case TTK_Union:
> EntityInfo.kind = CXIdxEntity_Union; break;
> case TTK_Class:
> - EntityInfo.kind = CXIdxEntity_CXXClass;
> - EntityInfo.lang = CXIdxEntityLang_CXX;
> - break;
> - case TTK_Enum:
> - EntityInfo.kind = CXIdxEntity_Enum; break;
> - }
> + EntityInfo.kind = CXIdxEntity_CXXClass;
> + EntityInfo.lang = CXIdxEntityLang_CXX;
> + break;
> + case TTK_Interface:
> + EntityInfo.kind = CXIdxEntity_CXXInterface;
> + EntityInfo.lang = CXIdxEntityLang_CXX;
> + break;
> + case TTK_Enum:
> + EntityInfo.kind = CXIdxEntity_Enum; break;
> + }
>
> if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D))
> if (!CXXRec->isCLike())
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list