Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -961,7 +961,8 @@ let Spellings = [Clang<"external_source_symbol">]; let Args = [StringArgument<"language", 1>, StringArgument<"definedIn", 1>, - BoolArgument<"generatedDeclaration", 1>]; + BoolArgument<"generatedDeclaration", 1>, + StringArgument<"USR", 1>]; let HasCustomParsing = 1; let Subjects = SubjectList<[Named]>; let Documentation = [ExternalSourceSymbolDocs]; Index: clang/include/clang/Basic/AttrDocs.td =================================================================== --- clang/include/clang/Basic/AttrDocs.td +++ clang/include/clang/Basic/AttrDocs.td @@ -1750,6 +1750,19 @@ source containers are modules, so ``defined_in`` should specify the Swift module name. +USR=\ *string-literal* + String that specifies a unified symbol resolution (USR) value for this + declaration. USR string uniquely identifies this particular declaration, and + is typically used when constructing an index of a codebase. + The USR value in this attribute is expected to be generated by an external + compiler that compiled the native declaration using its original source + language. The exact format of the USR string and its other attributes + are determined by the specification of this declaration's source language. + When not specified, Clang's indexer will use the Clang USR for this symbol. + User can query to see if Clang supports the use of the ``USR`` clause in + the ``external_source_symbol`` attribute with + ``__has_attribute(external_source_symbol_with_usr)``. + generated_declaration This declaration was automatically generated by some tool. Index: clang/include/clang/Basic/DiagnosticCommonKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticCommonKinds.td +++ clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -55,7 +55,7 @@ def err_expected_string_literal : Error<"expected string literal " "%select{in %1|for diagnostic message in static_assert|" "for optional message in 'availability' attribute|" - "for %select{language|source container}1 name in " + "for %select{language name|source container name|USR}1 in " "'external_source_symbol' attribute}0">; def err_invalid_string_udl : Error< "string literal with user-defined suffix cannot be used here">; Index: clang/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticParseKinds.td +++ clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1104,7 +1104,7 @@ // External source symbol attribute def err_external_source_symbol_expected_keyword : Error< - "expected 'language', 'defined_in', or 'generated_declaration'">; + "expected 'language', 'defined_in', 'generated_declaration', or 'USR'">; def err_external_source_symbol_duplicate_clause : Error< "duplicate %0 clause in an 'external_source_symbol' attribute">; Index: clang/include/clang/Parse/Parser.h =================================================================== --- clang/include/clang/Parse/Parser.h +++ clang/include/clang/Parse/Parser.h @@ -155,7 +155,7 @@ /// Identifiers used by the 'external_source_symbol' attribute. IdentifierInfo *Ident_language, *Ident_defined_in, - *Ident_generated_declaration; + *Ident_generated_declaration, *Ident_USR; /// C++11 contextual keywords. mutable IdentifierInfo *Ident_final; Index: clang/lib/Basic/Attributes.cpp =================================================================== --- clang/lib/Basic/Attributes.cpp +++ clang/lib/Basic/Attributes.cpp @@ -27,6 +27,10 @@ ScopeName == "omp") return (Name == "directive" || Name == "sequence") ? 1 : 0; + // Special case additions of new clauses to existing attributes. + if (Name == "external_source_symbol_with_usr") + return 1; + #include "clang/Basic/AttrHasAttributeImpl.inc" return 0; Index: clang/lib/Index/USRGeneration.cpp =================================================================== --- clang/lib/Index/USRGeneration.cpp +++ clang/lib/Index/USRGeneration.cpp @@ -1139,6 +1139,15 @@ // C++'s operator new function, can have invalid locations but it is fine to // create USRs that can identify them. + // Check if the declaration has explicit external USR specified. + auto *CD = D->getCanonicalDecl(); + if (auto *ExternalSymAttr = CD->getAttr()) { + if (!ExternalSymAttr->getUSR().empty()) { + llvm::raw_svector_ostream Out(Buf); + Out << ExternalSymAttr->getUSR(); + return false; + } + } USRGenerator UG(&D->getASTContext(), Buf); UG.Visit(D); return UG.ignoreResults(); Index: clang/lib/Parse/ParseDecl.cpp =================================================================== --- clang/lib/Parse/ParseDecl.cpp +++ clang/lib/Parse/ParseDecl.cpp @@ -1328,6 +1328,7 @@ /// keyword-arg: /// 'language' '=' /// 'defined_in' '=' +/// 'USR' '=' /// 'generated_declaration' void Parser::ParseExternalSourceSymbolAttribute( IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc, @@ -1343,6 +1344,7 @@ Ident_language = PP.getIdentifierInfo("language"); Ident_defined_in = PP.getIdentifierInfo("defined_in"); Ident_generated_declaration = PP.getIdentifierInfo("generated_declaration"); + Ident_USR = PP.getIdentifierInfo("USR"); } ExprResult Language; @@ -1350,6 +1352,8 @@ ExprResult DefinedInExpr; bool HasDefinedIn = false; IdentifierLoc *GeneratedDeclaration = nullptr; + ExprResult USR; + bool HasUSR = false; // Parse the language/defined_in/generated_declaration keywords do { @@ -1371,7 +1375,8 @@ continue; } - if (Keyword != Ident_language && Keyword != Ident_defined_in) { + if (Keyword != Ident_language && Keyword != Ident_defined_in && + Keyword != Ident_USR) { Diag(Tok, diag::err_external_source_symbol_expected_keyword); SkipUntil(tok::r_paren, StopAtSemi); return; @@ -1384,16 +1389,22 @@ return; } - bool HadLanguage = HasLanguage, HadDefinedIn = HasDefinedIn; + bool HadLanguage = HasLanguage, HadDefinedIn = HasDefinedIn, + HadUSR = HasUSR; if (Keyword == Ident_language) HasLanguage = true; + else if (Keyword == Ident_USR) + HasUSR = 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); + << /*language | source container | USR*/ ( + Keyword == Ident_language + ? 0 + : (Keyword == Ident_defined_in ? 1 : 2)); SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch); continue; } @@ -1405,6 +1416,14 @@ continue; } Language = ParseStringLiteralExpression(); + } else if (Keyword == Ident_USR) { + if (HadUSR) { + Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause) + << Keyword; + ParseStringLiteralExpression(); + continue; + } + USR = ParseStringLiteralExpression(); } else { assert(Keyword == Ident_defined_in && "Invalid clause keyword!"); if (HadDefinedIn) { @@ -1423,8 +1442,8 @@ if (EndLoc) *EndLoc = T.getCloseLocation(); - ArgsUnion Args[] = {Language.get(), DefinedInExpr.get(), - GeneratedDeclaration}; + ArgsUnion Args[] = {Language.get(), DefinedInExpr.get(), GeneratedDeclaration, + USR.get()}; Attrs.addNew(&ExternalSourceSymbol, SourceRange(Loc, T.getCloseLocation()), ScopeName, ScopeLoc, Args, std::size(Args), Syntax); } Index: clang/lib/Parse/Parser.cpp =================================================================== --- clang/lib/Parse/Parser.cpp +++ clang/lib/Parse/Parser.cpp @@ -522,7 +522,8 @@ Ident_strict = nullptr; Ident_replacement = nullptr; - Ident_language = Ident_defined_in = Ident_generated_declaration = nullptr; + Ident_language = Ident_defined_in = Ident_generated_declaration = Ident_USR = + nullptr; Ident__except = nullptr; Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -2834,7 +2834,7 @@ static void handleExternalSourceSymbolAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 3)) + if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 4)) return; StringRef Language; @@ -2844,9 +2844,12 @@ if (const auto *SE = dyn_cast_or_null(AL.getArgAsExpr(1))) DefinedIn = SE->getString(); bool IsGeneratedDeclaration = AL.getArgAsIdent(2) != nullptr; + StringRef USR; + if (const auto *SE = dyn_cast_or_null(AL.getArgAsExpr(3))) + USR = SE->getString(); D->addAttr(::new (S.Context) ExternalSourceSymbolAttr( - S.Context, AL, Language, DefinedIn, IsGeneratedDeclaration)); + S.Context, AL, Language, DefinedIn, IsGeneratedDeclaration, USR)); } template Index: clang/test/AST/ast-dump-attr.cpp =================================================================== --- clang/test/AST/ast-dump-attr.cpp +++ clang/test/AST/ast-dump-attr.cpp @@ -175,7 +175,7 @@ void TestExternalSourceSymbolAttr2() __attribute__((external_source_symbol(defined_in="module", language="Swift"))); // CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr2 -// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module"{{$}} +// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" ""{{$}} void TestExternalSourceSymbolAttr3() __attribute__((external_source_symbol(generated_declaration, language="Objective-C++", defined_in="module"))); @@ -192,6 +192,11 @@ // CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr5 // CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration +void TestExternalSourceSymbolAttr6() +__attribute__((external_source_symbol(generated_declaration, defined_in="module", language="Swift", USR="testUSR"))); +// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr6 +// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration "testUSR" + namespace TestNoEscape { void noescapeFunc(int *p0, __attribute__((noescape)) int *p1) {} // CHECK: `-FunctionDecl{{.*}} noescapeFunc 'void (int *, __attribute__((noescape)) int *)' Index: clang/test/Index/Core/external-source-symbol-attr.m =================================================================== --- clang/test/Index/Core/external-source-symbol-attr.m +++ clang/test/Index/Core/external-source-symbol-attr.m @@ -4,6 +4,8 @@ #define GEN_DECL(mod_name) __attribute__((external_source_symbol(language="Swift", defined_in=mod_name, generated_declaration))) #define PUSH_GEN_DECL(mod_name) push(GEN_DECL(mod_name), apply_to=any(enum, objc_interface, objc_category, objc_protocol)) +#define GEN_DECL_USR(mod_name, usr) __attribute__((external_source_symbol(language="Swift", defined_in=mod_name, USR=usr, generated_declaration))) + // Forward declarations should not affect module namespacing below @class I1; @class I2; @@ -110,3 +112,10 @@ [i3 meth_other_mod]; // CHECK: [[@LINE-1]]:7 | instance-method/Swift | meth_other_mod | c:@CM@other_mod_for_cat@modname@objc(cs)I3(im)meth_other_mod | } + +void function() GEN_DECL_USR("SwiftMod", "s:8SwiftMod8functionyyF"); + +void test4() { + function(); + // CHECK: [[@LINE-1]]:3 | function/Swift | function | s:8SwiftMod8functionyyF +} Index: clang/test/Parser/attr-external-source-symbol.m =================================================================== --- clang/test/Parser/attr-external-source-symbol.m +++ clang/test/Parser/attr-external-source-symbol.m @@ -14,10 +14,14 @@ CaseB __attribute__((external_source_symbol(generated_declaration, language="Swift"))) } __attribute__((external_source_symbol(language = "Swift"))); +void functionCustomUSR(void) __attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration, USR="s:6module17functionCustomUSRyyF"))); + +void functionCustomUSR2(void) __attribute__((external_source_symbol(language="Swift", defined_in="module", USR="s:6module18functionCustomUSR2yyF", generated_declaration))); + void f2(void) -__attribute__((external_source_symbol())); // expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}} +__attribute__((external_source_symbol())); // expected-error {{expected 'language', 'defined_in', 'generated_declaration', or 'USR'}} void f3(void) -__attribute__((external_source_symbol(invalid))); // expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}} +__attribute__((external_source_symbol(invalid))); // expected-error {{expected 'language', 'defined_in', 'generated_declaration', or 'USR'}} void f4(void) __attribute__((external_source_symbol(language))); // expected-error {{expected '=' after language}} void f5(void) @@ -31,6 +35,8 @@ __attribute__((external_source_symbol(language="Swift", language="Swift"))); // expected-error {{duplicate 'language' clause in an 'external_source_symbol' attribute}} void f9(void) __attribute__((external_source_symbol(defined_in="module", language="Swift", defined_in="foo"))); // expected-error {{duplicate 'defined_in' clause in an 'external_source_symbol' attribute}} +__attribute__((external_source_symbol(defined_in="module", language="Swift", USR="foo", USR="bar"))); // expected-error {{duplicate 'USR' clause in an 'external_source_symbol' attribute}} +void f9_1(void); void f10(void) __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}} @@ -45,16 +51,16 @@ __attribute__((external_source_symbol(language=Swift))); // expected-error {{expected string literal for language name in 'external_source_symbol' attribute}} void f14(void) -__attribute__((external_source_symbol(=))); // expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}} +__attribute__((external_source_symbol(=))); // expected-error {{expected 'language', 'defined_in', 'generated_declaration', or 'USR'}} void f15(void) -__attribute__((external_source_symbol(="Swift"))); // expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}} +__attribute__((external_source_symbol(="Swift"))); // expected-error {{expected 'language', 'defined_in', 'generated_declaration', or 'USR'}} void f16(void) -__attribute__((external_source_symbol("Swift", "module", generated_declaration))); // expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}} +__attribute__((external_source_symbol("Swift", "module", generated_declaration))); // expected-error {{expected 'language', 'defined_in', 'generated_declaration', or 'USR'}} void f17(void) -__attribute__((external_source_symbol(language="Swift", "generated_declaration"))); // expected-error {{expected 'language', 'defined_in', or 'generated_declaration'}} +__attribute__((external_source_symbol(language="Swift", "generated_declaration"))); // expected-error {{expected 'language', 'defined_in', 'generated_declaration', or 'USR'}} void f18(void) __attribute__((external_source_symbol(language= =))); // expected-error {{expected string literal for language name in 'external_source_symbol' attribute}} @@ -81,4 +87,11 @@ __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(void) -__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'}} +__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', 'generated_declaration', or 'USR'}} + +void f27(void) +__attribute__((external_source_symbol(USR=f27))); // expected-error {{expected string literal for USR in 'external_source_symbol' attribute}} + +#if !__has_attribute(external_source_symbol_with_usr) +# error "Missing __has_attribute" +#endif Index: clang/test/Sema/attr-external-source-symbol.c =================================================================== --- clang/test/Sema/attr-external-source-symbol.c +++ clang/test/Sema/attr-external-source-symbol.c @@ -4,7 +4,9 @@ void twoClauses(void) __attribute__((external_source_symbol(language="Swift", defined_in="module"))); -void fourClauses(void) __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 fourClauses(void) __attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration, USR="test"))); + +void fiveClauses(void) __attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration, generated_declaration, USR="test"))); // expected-error {{duplicate 'generated_declaration' clause in an 'external_source_symbol' attribute}} void oneClause(void) __attribute__((external_source_symbol(generated_declaration))); @@ -22,8 +24,8 @@ [[clang::external_source_symbol(language="Swift", defined_in="module")]] void twoClauses2(void); -[[clang::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 fourClauses2(void); +[[clang::external_source_symbol(language="Swift", defined_in="module", USR="test", generated_declaration, generated_declaration)]] // expected-error {{duplicate 'generated_declaration' clause in an 'external_source_symbol' attribute}} +void fiveClauses2(void); [[clang::external_source_symbol(generated_declaration)]] void oneClause2(void);