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