aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang-c/Index.h15
-rw-r--r--include/clang/AST/CanonicalType.h1
-rw-r--r--include/clang/AST/Decl.h3
-rw-r--r--include/clang/AST/DeclCXX.h16
-rw-r--r--include/clang/AST/Type.h5
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td14
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td14
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td238
-rw-r--r--include/clang/Basic/Specifiers.h13
-rw-r--r--include/clang/Basic/TokenKinds.def2
-rw-r--r--include/clang/Sema/DeclSpec.h4
-rw-r--r--lib/AST/DeclCXX.cpp30
-rw-r--r--lib/AST/MicrosoftMangle.cpp13
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp56
-rw-r--r--lib/AST/Type.cpp14
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp14
-rw-r--r--lib/Parse/ParseDecl.cpp7
-rw-r--r--lib/Parse/ParseDeclCXX.cpp72
-rw-r--r--lib/Sema/DeclSpec.cpp2
-rw-r--r--lib/Sema/SemaCodeComplete.cpp13
-rw-r--r--lib/Sema/SemaDecl.cpp76
-rw-r--r--lib/Sema/SemaDeclCXX.cpp44
-rw-r--r--lib/Sema/SemaExprCXX.cpp2
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp1
-rw-r--r--lib/Sema/SemaType.cpp40
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp18
-rw-r--r--test/Parser/MicrosoftExtensions.cpp34
-rw-r--r--tools/libclang/CIndexCXX.cpp17
-rw-r--r--tools/libclang/CIndexUSRs.cpp1867
-rw-r--r--tools/libclang/IndexingContext.cpp16
30 files changed, 1414 insertions, 1247 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 1347f6c167..9ed0570cf6 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -4962,13 +4962,14 @@ typedef enum {
CXIdxEntity_CXXStaticVariable = 19,
CXIdxEntity_CXXStaticMethod = 20,
CXIdxEntity_CXXInstanceMethod = 21,
- CXIdxEntity_CXXConstructor = 22,
- CXIdxEntity_CXXDestructor = 23,
- CXIdxEntity_CXXConversionFunction = 24,
- CXIdxEntity_CXXTypeAlias = 25
-
-} CXIdxEntityKind;
-
+ CXIdxEntity_CXXConstructor = 22,
+ CXIdxEntity_CXXDestructor = 23,
+ CXIdxEntity_CXXConversionFunction = 24,
+ CXIdxEntity_CXXTypeAlias = 25,
+ CXIdxEntity_CXXInterface = 26
+
+} CXIdxEntityKind;
+
typedef enum {
CXIdxEntityLang_None = 0,
CXIdxEntityLang_C = 1,
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 6cce88868d..ea307bf307 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -276,6 +276,7 @@ public:
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)
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index e9f25b368a..5dcc104874 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -2448,7 +2448,7 @@ public:
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 @@ public:
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; }
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 65a0dab5c2..676d0f9e9e 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -1553,13 +1553,15 @@ public:
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
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 6564b66548..8630011929 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -1512,6 +1512,7 @@ public:
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 @@ public:
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 TagTypeKind {
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.
diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
index 9cfe5efae2..c64060081f 100644
--- a/include/clang/Basic/DiagnosticASTKinds.td
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -134,13 +134,13 @@ def note_odr_defined_here : Note<"also defined here">;
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<
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index f88a9dd4a6..53d58c085c 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -573,13 +573,13 @@ def err_expected_semi_after_tagdecl : Error<
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<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 05877705af..ead6159e5b 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -793,16 +793,17 @@ def err_friend_is_member : Error<
"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_ref_qualifier_constructor : Error<
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_auto_variable_cannot_appear_in_own_initializer : Error<
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 @@ def warn_cxx98_compat_constexpr : Warning<
"'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_var_requires_const_init : Error<
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 @@ def warn_unhandled_ms_attribute_ignored : Warning<
"__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_redefinition_different_typedef : Error<
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 err_array_too_large : Error<
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_struct : Extension<
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 @@ def err_invalid_declarator_scope : Error<"cannot define or redeclare %0 here "
"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 @@ def err_module_private_specialization : Error<
"%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 {
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index 96cada1057..1d39c4bdcf 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -50,12 +50,13 @@ namespace clang {
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
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index fc031914a8..fd0437c07b 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -505,6 +505,7 @@ KEYWORD(__if_not_exists , KEYMS)
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("_thiscall" , __thiscall , KEYMS)
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)
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 792b0c643d..9723a43c91 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -266,6 +266,7 @@ public:
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 @@ private:
}
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
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 2f21e4cbd6..c68a16bdae 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -463,13 +463,14 @@ void CXXRecordDecl::markedConstructorConstexpr(CXXConstructorDecl *CD) {
}
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 @@ NotASpecialMember:;
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;
}
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 982e3aceec..f0041b2422 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -1270,12 +1270,13 @@ void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) {
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:
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index d5df63f7d1..043e46e9d6 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -2260,12 +2260,28 @@ RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
}
// 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 @@ void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
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
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 7445152d62..c54250a479 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -357,9 +357,15 @@ bool Type::isStructureType() const {
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 @@ TypeWithKeyword::getKeywordForTypeSpec(unsigned TypeSpec) {
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 @@ TypeWithKeyword::getTagTypeKindForTypeSpec(unsigned TypeSpec) {
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 @@ TypeWithKeyword::getKeywordForTagTypeKind(TagTypeKind Kind) {
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 @@ TypeWithKeyword::getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword) {
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 @@ TypeWithKeyword::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) {
return false;
case ETK_Class:
case ETK_Struct:
+ case ETK_Interface:
case ETK_Union:
case ETK_Enum:
return true;
@@ -1381,6 +1392,7 @@ TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
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";
}
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index d5cf4d0b0e..212923421b 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -520,13 +520,13 @@ llvm::DIType CGDebugInfo::createRecordFwdDecl(const RecordDecl *RD,
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!");
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 28d8811b9b..bcc9106eb7 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1875,6 +1875,9 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
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 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// 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 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
// 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 @@ bool Parser::isTypeSpecifierQualifier() {
// 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 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw_class:
case tok::kw_struct:
case tok::kw_union:
+ case tok::kw___interface:
// enum-specifier
case tok::kw_enum:
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 42ec6b0205..e5740112bb 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1031,12 +1031,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
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 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
}
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 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
(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 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// 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 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
/// 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");
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 8fdb07029a..86833c0e94 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -270,6 +270,7 @@ bool Declarator::isDeclarationOfFunction() const {
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 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
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";
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 05b22fa537..15737b3928 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -1059,10 +1059,12 @@ bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
// 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 @@ static const char *GetCompletionTypeString(QualType T,
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 @@ static void addThisCompletion(Sema &S, ResultBuilder &Results) {
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 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) {
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 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
case DeclSpec::TST_struct:
case DeclSpec::TST_class:
+ case DeclSpec::TST_interface:
Filter = &ResultBuilder::IsClassOrStruct;
ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
break;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 048dbb68cb..93e07bef62 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -350,8 +350,8 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
/// 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 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
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 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result,
FixItTagName = "struct ";
break;
+ case TTK_Interface:
+ TagName = "__interface";
+ FixItTagName = "__interface ";
+ break;
+
case TTK_Union:
TagName = "union";
FixItTagName = "union ";
@@ -2604,6 +2610,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
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 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
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 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
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 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
<< 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 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
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 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
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 @@ bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
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 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
// 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 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
// 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 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
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 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
}
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;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 176e3fecb9..bae03f25af 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -672,12 +672,28 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
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 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) {
// 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;
}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 4fc9abd5c9..4efab1b83b 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2998,7 +2998,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
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();
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index aece90b785..6147d63ef4 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -727,6 +727,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_enum:
case TST_union:
case TST_struct:
+ case TST_interface:
case TST_class:
case TST_auto:
case TST_unknown_anytype:
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 94ddc239cd..0935e2e2e0 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -753,7 +753,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
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 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
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 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
}
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 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
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 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
// 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(),
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 1014658c39..b454cc341c 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1716,14 +1716,16 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
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)) {
diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp
index 6219e29f59..d1e8866929 100644
--- a/test/Parser/MicrosoftExtensions.cpp
+++ b/test/Parser/MicrosoftExtensions.cpp
@@ -171,19 +171,27 @@ void redundant_typename() {
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 {
diff --git a/tools/libclang/CIndexCXX.cpp b/tools/libclang/CIndexCXX.cpp
index 240b0f6c1f..1747949149 100644
--- a/tools/libclang/CIndexCXX.cpp
+++ b/tools/libclang/CIndexCXX.cpp
@@ -64,14 +64,15 @@ enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {
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;
diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp
index c885dd546c..613bb09a37 100644
--- a/tools/libclang/CIndexUSRs.cpp
+++ b/tools/libclang/CIndexUSRs.cpp
@@ -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"
diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp
index ace5c75a96..54f8d345e1 100644
--- a/tools/libclang/IndexingContext.cpp
+++ b/tools/libclang/IndexingContext.cpp
@@ -852,12 +852,16 @@ void IndexingContext::getEntityInfo(const NamedDecl *D,
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())