r296649 - Introduce an 'external_source_symbol' attribute that describes the origin
Alex Lorenz via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 1 10:06:25 PST 2017
Author: arphaman
Date: Wed Mar 1 12:06:25 2017
New Revision: 296649
URL: http://llvm.org/viewvc/llvm-project?rev=296649&view=rev
Log:
Introduce an 'external_source_symbol' attribute that describes the origin
and the nature of a declaration
This commit adds an external_source_symbol attribute to Clang. This attribute
specifies that a declaration originates from an external source and describes
the nature of that source. This attribute will be used to improve IDE features
like 'jump-to-definition' for mixed-language projects or project that use
auto-generated code.
rdar://30423368
Differential Revision: https://reviews.llvm.org/D29819
Added:
cfe/trunk/test/Parser/attr-external-source-symbol-cxx11.cpp
cfe/trunk/test/Parser/attr-external-source-symbol.m
cfe/trunk/test/Sema/attr-external-source-symbol.c
Modified:
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/Basic/AttrDocs.td
cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/AttributeList.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/test/Misc/ast-dump-attr.cpp
Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=296649&r1=296648&r2=296649&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Wed Mar 1 12:06:25 2017
@@ -527,6 +527,17 @@ def Availability : InheritableAttr {
let Documentation = [AvailabilityDocs];
}
+def ExternalSourceSymbol : InheritableAttr {
+ let Spellings = [GNU<"external_source_symbol">,
+ CXX11<"clang", "external_source_symbol">];
+ let Args = [StringArgument<"language", 1>,
+ StringArgument<"definedIn", 1>,
+ BoolArgument<"generatedDeclaration", 1>];
+ let HasCustomParsing = 1;
+// let Subjects = SubjectList<[Named]>;
+ let Documentation = [ExternalSourceSymbolDocs];
+}
+
def Blocks : InheritableAttr {
let Spellings = [GNU<"blocks">];
let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=296649&r1=296648&r2=296649&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
+++ cfe/trunk/include/clang/Basic/AttrDocs.td Wed Mar 1 12:06:25 2017
@@ -960,6 +960,63 @@ When one method overrides another, the o
}];
}
+def ExternalSourceSymbolDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``external_source_symbol`` attribute specifies that a declaration originates
+from an external source and describes the nature of that source.
+
+The fact that Clang is capable of recognizing declarations that were defined
+externally can be used to provide better tooling support for mixed-language
+projects or projects that rely on auto-generated code. For instance, an IDE that
+uses Clang and that supports mixed-language projects can use this attribute to
+provide a correct 'jump-to-definition' feature. For a concrete example,
+consider a protocol that's defined in a Swift file:
+
+.. code-block:: swift
+
+ @objc public protocol SwiftProtocol {
+ func method()
+ }
+
+This protocol can be used from Objective-C code by including a header file that
+was generated by the Swift compiler. The declarations in that header can use
+the ``external_source_symbol`` attribute to make Clang aware of the fact
+that ``SwiftProtocol`` actually originates from a Swift module:
+
+.. code-block:: objc
+
+ __attribute__((external_source_symbol(language=Swift,defined_in="module")))
+ @protocol SwiftProtocol
+ @required
+ - (void) method;
+ @end
+
+Consequently, when 'jump-to-definition' is performed at a location that
+references ``SwiftProtocol``, the IDE can jump to the original definition in
+the Swift source file rather than jumping to the Objective-C declaration in the
+auto-generated header file.
+
+The ``external_source_symbol`` attribute is a comma-separated list that includes
+clauses that describe the origin and the nature of the particular declaration.
+Those clauses can be:
+
+language=\ *string-literal*
+ The name of the source language in which this declaration was defined.
+
+defined_in=\ *string-literal*
+ The name of the source container in which the declaration was defined. The
+ exact definition of source container is language-specific, e.g. Swift's
+ source containers are modules, so ``defined_in`` should specify the Swift
+ module name.
+
+generated_declaration
+ This declaration was automatically generated by some tool.
+
+The clauses can be specified in any order. The clauses that are listed above are
+all optional, but the attribute has to have at least one clause.
+ }];
+}
def RequireConstantInitDocs : Documentation {
let Category = DocCatVariable;
Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=296649&r1=296648&r2=296649&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Wed Mar 1 12:06:25 2017
@@ -45,7 +45,9 @@ def err_expected_colon_after_setter_name
"must end with ':'">;
def err_expected_string_literal : Error<"expected string literal "
"%select{in %1|for diagnostic message in static_assert|"
- "for optional message in 'availability' attribute}0">;
+ "for optional message in 'availability' attribute|"
+ "for %select{language|source container}1 name in "
+ "'external_source_symbol' attribute}0">;
def err_invalid_string_udl : Error<
"string literal with user-defined suffix cannot be used here">;
def err_invalid_character_udl : Error<
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=296649&r1=296648&r2=296649&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Mar 1 12:06:25 2017
@@ -859,6 +859,12 @@ def err_availability_query_repeated_plat
def err_availability_query_repeated_star : Error<
"'*' query has already been specified">;
+// External source symbol attribute
+def err_external_source_symbol_expected_keyword : Error<
+ "expected 'language', 'defined_in', or 'generated_declaration'">;
+def err_external_source_symbol_duplicate_clause : Error<
+ "duplicate %0 clause in an 'external_source_symbol' attribute">;
+
// Type safety attributes
def err_type_safety_unknown_flag : Error<
"invalid comparison flag %0; use 'layout_compatible' or 'must_be_null'">;
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=296649&r1=296648&r2=296649&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Mar 1 12:06:25 2017
@@ -2754,7 +2754,8 @@ def warn_attribute_wrong_decl_type : War
"|functions, methods, enums, and classes"
"|structs, classes, variables, functions, and inline namespaces"
"|variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members"
- "|classes and enumerations}1">,
+ "|classes and enumerations"
+ "|named declarations}1">,
InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>;
def warn_type_attribute_wrong_type : Warning<
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=296649&r1=296648&r2=296649&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Mar 1 12:06:25 2017
@@ -142,6 +142,10 @@ class Parser : public CodeCompletionHand
/// \brief Identifier for "replacement".
IdentifierInfo *Ident_replacement;
+ /// Identifiers used by the 'external_source_symbol' attribute.
+ IdentifierInfo *Ident_language, *Ident_defined_in,
+ *Ident_generated_declaration;
+
/// C++0x contextual keywords.
mutable IdentifierInfo *Ident_final;
mutable IdentifierInfo *Ident_GNU_final;
@@ -2197,6 +2201,12 @@ private:
Declarator *D);
IdentifierLoc *ParseIdentifierLoc();
+ unsigned
+ ParseClangAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax);
+
void MaybeParseCXX11Attributes(Declarator &D) {
if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
ParsedAttributesWithRange attrs(AttrFactory);
@@ -2286,6 +2296,14 @@ private:
Optional<AvailabilitySpec> ParseAvailabilitySpec();
ExprResult ParseAvailabilityCheckExpr(SourceLocation StartLoc);
+ void ParseExternalSourceSymbolAttribute(IdentifierInfo &ExternalSourceSymbol,
+ SourceLocation Loc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax);
+
void ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
SourceLocation ObjCBridgeRelatedLoc,
ParsedAttributes &attrs,
Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=296649&r1=296648&r2=296649&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Wed Mar 1 12:06:25 2017
@@ -927,6 +927,7 @@ enum AttributeDeclKind {
ExpectedStructClassVariableFunctionOrInlineNamespace,
ExpectedForMaybeUnused,
ExpectedEnumOrClass,
+ ExpectedNamedDecl,
};
} // end namespace clang
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=296649&r1=296648&r2=296649&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Mar 1 12:06:25 2017
@@ -356,6 +356,10 @@ void Parser::ParseGNUAttributeArgs(Ident
ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
ScopeLoc, Syntax);
return;
+ } else if (AttrKind == AttributeList::AT_ExternalSourceSymbol) {
+ ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
+ return;
} else if (AttrKind == AttributeList::AT_ObjCBridgeRelated) {
ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, Syntax);
@@ -389,6 +393,25 @@ void Parser::ParseGNUAttributeArgs(Ident
ScopeLoc, Syntax);
}
+unsigned Parser::ParseClangAttributeArgs(
+ IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc, AttributeList::Syntax Syntax) {
+ assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
+
+ AttributeList::Kind AttrKind =
+ AttributeList::getKind(AttrName, ScopeName, Syntax);
+
+ if (AttrKind == AttributeList::AT_ExternalSourceSymbol) {
+ ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
+ return Attrs.getList() ? Attrs.getList()->getNumArgs() : 0;
+ }
+
+ return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
+}
+
bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs) {
@@ -1064,6 +1087,119 @@ void Parser::ParseAvailabilityAttribute(
Syntax, StrictLoc, ReplacementExpr.get());
}
+/// \brief Parse the contents of the "external_source_symbol" attribute.
+///
+/// external-source-symbol-attribute:
+/// 'external_source_symbol' '(' keyword-arg-list ')'
+///
+/// keyword-arg-list:
+/// keyword-arg
+/// keyword-arg ',' keyword-arg-list
+///
+/// keyword-arg:
+/// 'language' '=' <string>
+/// 'defined_in' '=' <string>
+/// 'generated_declaration'
+void Parser::ParseExternalSourceSymbolAttribute(
+ IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc, AttributeList::Syntax Syntax) {
+ // Opening '('.
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.expectAndConsume())
+ return;
+
+ // Initialize the pointers for the keyword identifiers when required.
+ if (!Ident_language) {
+ Ident_language = PP.getIdentifierInfo("language");
+ Ident_defined_in = PP.getIdentifierInfo("defined_in");
+ Ident_generated_declaration = PP.getIdentifierInfo("generated_declaration");
+ }
+
+ ExprResult Language;
+ bool HasLanguage = false;
+ ExprResult DefinedInExpr;
+ bool HasDefinedIn = false;
+ IdentifierLoc *GeneratedDeclaration = nullptr;
+
+ // Parse the language/defined_in/generated_declaration keywords
+ do {
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_external_source_symbol_expected_keyword);
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ SourceLocation KeywordLoc = Tok.getLocation();
+ IdentifierInfo *Keyword = Tok.getIdentifierInfo();
+ if (Keyword == Ident_generated_declaration) {
+ if (GeneratedDeclaration) {
+ Diag(Tok, diag::err_external_source_symbol_duplicate_clause) << Keyword;
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+ GeneratedDeclaration = ParseIdentifierLoc();
+ continue;
+ }
+
+ if (Keyword != Ident_language && Keyword != Ident_defined_in) {
+ Diag(Tok, diag::err_external_source_symbol_expected_keyword);
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ ConsumeToken();
+ if (ExpectAndConsume(tok::equal, diag::err_expected_after,
+ Keyword->getName())) {
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+
+ bool HadLanguage = HasLanguage, HadDefinedIn = HasDefinedIn;
+ if (Keyword == Ident_language)
+ HasLanguage = true;
+ else
+ HasDefinedIn = true;
+
+ if (Tok.isNot(tok::string_literal)) {
+ Diag(Tok, diag::err_expected_string_literal)
+ << /*Source='external_source_symbol attribute'*/ 3
+ << /*language | source container*/ (Keyword != Ident_language);
+ SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);
+ continue;
+ }
+ if (Keyword == Ident_language) {
+ if (HadLanguage) {
+ Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)
+ << Keyword;
+ ParseStringLiteralExpression();
+ continue;
+ }
+ Language = ParseStringLiteralExpression();
+ } else {
+ assert(Keyword == Ident_defined_in && "Invalid clause keyword!");
+ if (HadDefinedIn) {
+ Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)
+ << Keyword;
+ ParseStringLiteralExpression();
+ continue;
+ }
+ DefinedInExpr = ParseStringLiteralExpression();
+ }
+ } while (TryConsumeToken(tok::comma));
+
+ // Closing ')'.
+ if (T.consumeClose())
+ return;
+ if (EndLoc)
+ *EndLoc = T.getCloseLocation();
+
+ ArgsUnion Args[] = {Language.get(), DefinedInExpr.get(),
+ GeneratedDeclaration};
+ Attrs.addNew(&ExternalSourceSymbol, SourceRange(Loc, T.getCloseLocation()),
+ ScopeName, ScopeLoc, Args, llvm::array_lengthof(Args), Syntax);
+}
+
/// \brief Parse the contents of the "objc_bridge_related" attribute.
/// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')'
/// related_class:
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=296649&r1=296648&r2=296649&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed Mar 1 12:06:25 2017
@@ -3823,36 +3823,44 @@ bool Parser::ParseCXX11AttributeArgs(Ide
return false;
}
- if (ScopeName && ScopeName->getName() == "gnu")
+ if (ScopeName && ScopeName->getName() == "gnu") {
// GNU-scoped attributes have some special cases to handle GNU-specific
// behaviors.
ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
ScopeLoc, AttributeList::AS_CXX11, nullptr);
- else {
- unsigned NumArgs =
+ return true;
+ }
+
+ unsigned NumArgs;
+ // Some Clang-scoped attributes have some special parsing behavior.
+ if (ScopeName && ScopeName->getName() == "clang")
+ NumArgs =
+ ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+ ScopeLoc, AttributeList::AS_CXX11);
+ else
+ NumArgs =
ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
ScopeName, ScopeLoc, AttributeList::AS_CXX11);
-
- const AttributeList *Attr = Attrs.getList();
- if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
- // If the attribute is a standard or built-in attribute and we are
- // parsing an argument list, we need to determine whether this attribute
- // was allowed to have an argument list (such as [[deprecated]]), and how
- // many arguments were parsed (so we can diagnose on [[deprecated()]]).
- if (Attr->getMaxArgs() && !NumArgs) {
- // The attribute was allowed to have arguments, but none were provided
- // even though the attribute parsed successfully. This is an error.
- Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName;
- Attr->setInvalid(true);
- } else if (!Attr->getMaxArgs()) {
- // The attribute parsed successfully, but was not allowed to have any
- // arguments. It doesn't matter whether any were provided -- the
- // presence of the argument list (even if empty) is diagnosed.
- Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)
- << AttrName
- << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc));
- Attr->setInvalid(true);
- }
+
+ const AttributeList *Attr = Attrs.getList();
+ if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
+ // If the attribute is a standard or built-in attribute and we are
+ // parsing an argument list, we need to determine whether this attribute
+ // was allowed to have an argument list (such as [[deprecated]]), and how
+ // many arguments were parsed (so we can diagnose on [[deprecated()]]).
+ if (Attr->getMaxArgs() && !NumArgs) {
+ // The attribute was allowed to have arguments, but none were provided
+ // even though the attribute parsed successfully. This is an error.
+ Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName;
+ Attr->setInvalid(true);
+ } else if (!Attr->getMaxArgs()) {
+ // The attribute parsed successfully, but was not allowed to have any
+ // arguments. It doesn't matter whether any were provided -- the
+ // presence of the argument list (even if empty) is diagnosed.
+ Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)
+ << AttrName
+ << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc));
+ Attr->setInvalid(true);
}
}
return true;
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=296649&r1=296648&r2=296649&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Wed Mar 1 12:06:25 2017
@@ -493,6 +493,8 @@ void Parser::Initialize() {
Ident_strict = nullptr;
Ident_replacement = nullptr;
+ Ident_language = Ident_defined_in = Ident_generated_declaration = nullptr;
+
Ident__except = nullptr;
Ident__exception_code = Ident__exception_info = nullptr;
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=296649&r1=296648&r2=296649&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Mar 1 12:06:25 2017
@@ -2409,6 +2409,32 @@ static void handleAvailabilityAttr(Sema
}
}
+static void handleExternalSourceSymbolAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ return;
+ assert(checkAttributeAtMostNumArgs(S, Attr, 3) &&
+ "Invalid number of arguments in an external_source_symbol attribute");
+
+ if (!isa<NamedDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedNamedDecl;
+ return;
+ }
+
+ StringRef Language;
+ if (const auto *SE = dyn_cast_or_null<StringLiteral>(Attr.getArgAsExpr(0)))
+ Language = SE->getString();
+ StringRef DefinedIn;
+ if (const auto *SE = dyn_cast_or_null<StringLiteral>(Attr.getArgAsExpr(1)))
+ DefinedIn = SE->getString();
+ bool IsGeneratedDeclaration = Attr.getArgAsIdent(2) != nullptr;
+
+ D->addAttr(::new (S.Context) ExternalSourceSymbolAttr(
+ Attr.getRange(), S.Context, Language, DefinedIn, IsGeneratedDeclaration,
+ Attr.getAttributeSpellingListIndex()));
+}
+
template <class T>
static T *mergeVisibilityAttr(Sema &S, Decl *D, SourceRange range,
typename T::VisibilityType value,
@@ -5805,6 +5831,9 @@ static void ProcessDeclAttribute(Sema &S
case AttributeList::AT_ExtVectorType:
handleExtVectorTypeAttr(S, scope, D, Attr);
break;
+ case AttributeList::AT_ExternalSourceSymbol:
+ handleExternalSourceSymbolAttr(S, D, Attr);
+ break;
case AttributeList::AT_MinSize:
handleMinSizeAttr(S, D, Attr);
break;
Modified: cfe/trunk/test/Misc/ast-dump-attr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-attr.cpp?rev=296649&r1=296648&r2=296649&view=diff
==============================================================================
--- cfe/trunk/test/Misc/ast-dump-attr.cpp (original)
+++ cfe/trunk/test/Misc/ast-dump-attr.cpp Wed Mar 1 12:06:25 2017
@@ -154,3 +154,28 @@ void f() {
struct __attribute__((objc_bridge_related(NSParagraphStyle,,))) TestBridgedRef;
// CHECK: CXXRecordDecl{{.*}} struct TestBridgedRef
// CHECK-NEXT: ObjCBridgeRelatedAttr{{.*}} NSParagraphStyle
+
+void TestExternalSourceSymbolAttr1()
+__attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration)));
+// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr1
+// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration
+
+void TestExternalSourceSymbolAttr2()
+__attribute__((external_source_symbol(defined_in="module", language="Swift")));
+// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr2
+// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module"{{$}}
+
+void TestExternalSourceSymbolAttr3()
+__attribute__((external_source_symbol(generated_declaration, language="Objective-C++", defined_in="module")));
+// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr3
+// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Objective-C++" "module" GeneratedDeclaration
+
+void TestExternalSourceSymbolAttr4()
+__attribute__((external_source_symbol(defined_in="Some external file.cs", generated_declaration, language="C Sharp")));
+// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr4
+// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "C Sharp" "Some external file.cs" GeneratedDeclaration
+
+void TestExternalSourceSymbolAttr5()
+__attribute__((external_source_symbol(generated_declaration, defined_in="module", language="Swift")));
+// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr5
+// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration
Added: cfe/trunk/test/Parser/attr-external-source-symbol-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/attr-external-source-symbol-cxx11.cpp?rev=296649&view=auto
==============================================================================
--- cfe/trunk/test/Parser/attr-external-source-symbol-cxx11.cpp (added)
+++ cfe/trunk/test/Parser/attr-external-source-symbol-cxx11.cpp Wed Mar 1 12:06:25 2017
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// expected-no-diagnostics
+
+[[clang::external_source_symbol(language="Swift", defined_in="module")]]
+void function() { }
Added: cfe/trunk/test/Parser/attr-external-source-symbol.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/attr-external-source-symbol.m?rev=296649&view=auto
==============================================================================
--- cfe/trunk/test/Parser/attr-external-source-symbol.m (added)
+++ cfe/trunk/test/Parser/attr-external-source-symbol.m Wed Mar 1 12:06:25 2017
@@ -0,0 +1,84 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void function() __attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration)));
+
+__attribute__((external_source_symbol(language="Swift", defined_in="module")))
+ at interface I
+
+- (void)method __attribute__((external_source_symbol(defined_in= "module")));
+
+ at end
+
+enum E {
+ CaseA __attribute__((external_source_symbol(generated_declaration))),
+ CaseB __attribute__((external_source_symbol(generated_declaration, language="Swift")))
+} __attribute__((external_source_symbol(language = "Swift")));
+
+void f2()
+__attribute__((external_source_symbol())); // expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}}
+void f3()
+__attribute__((external_source_symbol(invalid))); // expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}}
+void f4()
+__attribute__((external_source_symbol(language))); // expected-error {{expected '=' after language}}
+void f5()
+__attribute__((external_source_symbol(language=))); // expected-error {{expected string literal for language name in 'external_source_symbol' attribute}}
+void f6()
+__attribute__((external_source_symbol(defined_in=20))); // expected-error {{expected string literal for source container name in 'external_source_symbol' attribute}}
+
+void f7()
+__attribute__((external_source_symbol(generated_declaration, generated_declaration))); // expected-error {{duplicate 'generated_declaration' clause in an 'external_source_symbol' attribute}}
+void f8()
+__attribute__((external_source_symbol(language="Swift", language="Swift"))); // expected-error {{duplicate 'language' clause in an 'external_source_symbol' attribute}}
+void f9()
+__attribute__((external_source_symbol(defined_in="module", language="Swift", defined_in="foo"))); // expected-error {{duplicate 'defined_in' clause in an 'external_source_symbol' attribute}}
+
+void f10()
+__attribute__((external_source_symbol(generated_declaration, language="Swift", defined_in="foo", generated_declaration, generated_declaration, language="Swift"))); // expected-error {{duplicate 'generated_declaration' clause in an 'external_source_symbol' attribute}}
+
+void f11()
+__attribute__((external_source_symbol(language="Objective-C++", defined_in="Some file with spaces")));
+
+void f12()
+__attribute__((external_source_symbol(language="C Sharp", defined_in="file:////Hello world with spaces. cs")));
+
+void f13()
+__attribute__((external_source_symbol(language=Swift))); // expected-error {{expected string literal for language name in 'external_source_symbol' attribute}}
+
+void f14()
+__attribute__((external_source_symbol(=))); // expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}}
+
+void f15()
+__attribute__((external_source_symbol(="Swift"))); // expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}}
+
+void f16()
+__attribute__((external_source_symbol("Swift", "module", generated_declaration))); // expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}}
+
+void f17()
+__attribute__((external_source_symbol(language="Swift", "generated_declaration"))); // expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}}
+
+void f18()
+__attribute__((external_source_symbol(language= =))); // expected-error {{expected string literal for language name in 'external_source_symbol' attribute}}
+
+void f19()
+__attribute__((external_source_symbol(defined_in="module" language="swift"))); // expected-error {{expected ')'}} expected-note {{to match this '('}}
+
+void f20()
+__attribute__((external_source_symbol(defined_in="module" language="swift" generated_declaration))); // expected-error {{expected ')'}} expected-note {{to match this '('}}
+
+void f21()
+__attribute__((external_source_symbol(defined_in= language="swift"))); // expected-error {{expected string literal for source container name in 'external_source_symbol' attribute}}
+
+void f22()
+__attribute__((external_source_symbol)); // expected-error {{'external_source_symbol' attribute takes at least 1 argument}}
+
+void f23()
+__attribute__((external_source_symbol(defined_in=, language="swift" generated_declaration))); // expected-error {{expected string literal for source container name in 'external_source_symbol' attribute}} expected-error{{expected ')'}} expected-note{{to match this '('}}
+
+void f24()
+__attribute__((external_source_symbol(language = generated_declaration))); // expected-error {{expected string literal for language name in 'external_source_symbol' attribute}}
+
+void f25()
+__attribute__((external_source_symbol(defined_in=123, defined_in="module"))); // expected-error {{expected string literal for source container name in 'external_source_symbol'}} expected-error {{duplicate 'defined_in' clause in an 'external_source_symbol' attribute}}
+
+void f26()
+__attribute__((external_source_symbol(language=Swift, language="Swift", error))); // expected-error {{expected string literal for language name in 'external_source_symbol'}} expected-error {{duplicate 'language' clause in an 'external_source_symbol' attribute}} expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}}
Added: cfe/trunk/test/Sema/attr-external-source-symbol.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-external-source-symbol.c?rev=296649&view=auto
==============================================================================
--- cfe/trunk/test/Sema/attr-external-source-symbol.c (added)
+++ cfe/trunk/test/Sema/attr-external-source-symbol.c Wed Mar 1 12:06:25 2017
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
+
+void threeClauses() __attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration)));
+
+void twoClauses() __attribute__((external_source_symbol(language="Swift", defined_in="module")));
+
+void fourClauses() __attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration, generated_declaration))); // expected-error {{duplicate 'generated_declaration' clause in an 'external_source_symbol' attribute}}
+
+void oneClause() __attribute__((external_source_symbol(generated_declaration)));
+
+void noArguments()
+__attribute__((external_source_symbol)); // expected-error {{'external_source_symbol' attribute takes at least 1 argument}}
+
+void namedDeclsOnly() {
+ int (^block)(void) = ^ (void)
+ __attribute__((external_source_symbol(language="Swift"))) { // expected-warning {{'external_source_symbol' attribute only applies to named declarations}}
+ return 1;
+ };
+}
More information about the cfe-commits
mailing list