Skip to content

Commit

Permalink
Sema: introduce __attribute__((__swift_name__))
Browse files Browse the repository at this point in the history
This introduces the new `swift_name` attribute that allows annotating
APIs with an alternate spelling for Swift.  This is used as part of the
importing mechanism to allow interfaces to be imported with a new name
into Swift.  It takes a parameter which is the Swift function name.
This parameter is validated to check if it matches the possible
transformed signature in Swift.

This is based on the work of the original changes in
llvm/llvm-project-staging@8afaf3a

Differential Revision: https://reviews.llvm.org/D87534
Reviewed By: Aaron Ballman, Dmitri Gribenko
  • Loading branch information
compnerd committed Sep 22, 2020
1 parent be2158b commit 9bb5ecf
Show file tree
Hide file tree
Showing 8 changed files with 569 additions and 0 deletions.
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2162,6 +2162,12 @@ def SwiftError : InheritableAttr {
let Documentation = [SwiftErrorDocs];
}

def SwiftName : InheritableAttr {
let Spellings = [GNU<"swift_name">];
let Args = [StringArgument<"Name">];
let Documentation = [SwiftNameDocs];
}

def NoDeref : TypeAttr {
let Spellings = [Clang<"noderef">];
let Documentation = [NoDerefDocs];
Expand Down
24 changes: 24 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -3572,6 +3572,30 @@ The return type is left unmodified.
}];
}

def SwiftNameDocs : Documentation {
let Category = SwiftDocs;
let Heading = "swift_name";
let Content = [{
The ``swift_name`` attribute provides the name of the declaration in Swift. If
this attribute is absent, the name is transformed according to the algorithm
built into the Swift compiler.

The argument is a string literal that contains the Swift name of the function,
variable, or type. When renaming a function, the name may be a compound Swift
name. For a type, enum constant, property, or variable declaration, the name
must be a simple or qualified identifier.

.. code-block:: c

@interface URL
- (void) initWithString:(NSString *)s __attribute__((__swift_name__("URL.init(_:)")))
@end

void __attribute__((__swift_name__("squareRoot()"))) sqrt(double v) {
}
}];
}

def OMPDeclareSimdDocs : Documentation {
let Category = DocCatFunction;
let Heading = "#pragma omp declare simd";
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@ def StringCompare : DiagGroup<"string-compare">;
def StringPlusInt : DiagGroup<"string-plus-int">;
def StringPlusChar : DiagGroup<"string-plus-char">;
def StrncatSize : DiagGroup<"strncat-size">;
def SwiftNameAttribute : DiagGroup<"swift-name-attribute">;
def IntInBoolContext : DiagGroup<"int-in-bool-context">;
def TautologicalTypeLimitCompare : DiagGroup<"tautological-type-limit-compare">;
def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">;
Expand Down
40 changes: 40 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3974,6 +3974,46 @@ def err_objc_bridged_related_known_method : Error<
def err_objc_attr_protocol_requires_definition : Error<
"attribute %0 can only be applied to @protocol definitions, not forward declarations">;

// Swift attributes.
def warn_attr_swift_name_function
: Warning<"%0 attribute argument must be a string literal specifying a Swift function name">,
InGroup<SwiftNameAttribute>;
def warn_attr_swift_name_invalid_identifier
: Warning<"%0 attribute has invalid identifier for the %select{base|context|parameter}1 name">,
InGroup<SwiftNameAttribute>;
def warn_attr_swift_name_decl_kind
: Warning<"%0 attribute cannot be applied to this declaration">,
InGroup<SwiftNameAttribute>;
def warn_attr_swift_name_subscript_invalid_parameter
: Warning<"%0 attribute for 'subscript' must %select{be a getter or setter|"
"have at least one parameter|"
"have a 'self:' parameter}1">,
InGroup<SwiftNameAttribute>;
def warn_attr_swift_name_missing_parameters
: Warning<"%0 attribute is missing parameter label clause">,
InGroup<SwiftNameAttribute>;
def warn_attr_swift_name_setter_parameters
: Warning<"%0 attribute for setter must have one parameter for new value">,
InGroup<SwiftNameAttribute>;
def warn_attr_swift_name_multiple_selfs
: Warning<"%0 attribute cannot specify more than one 'self:' parameter">,
InGroup<SwiftNameAttribute>;
def warn_attr_swift_name_getter_parameters
: Warning<"%0 attribute for getter must not have any parameters besides 'self:'">,
InGroup<SwiftNameAttribute>;
def warn_attr_swift_name_subscript_setter_no_newValue
: Warning<"%0 attribute for 'subscript' setter must have a 'newValue:' parameter">,
InGroup<SwiftNameAttribute>;
def warn_attr_swift_name_subscript_setter_multiple_newValues
: Warning<"%0 attribute for 'subscript' setter cannot have multiple 'newValue:' parameters">,
InGroup<SwiftNameAttribute>;
def warn_attr_swift_name_subscript_getter_newValue
: Warning<"%0 attribute for 'subscript' getter cannot have a 'newValue:' parameter">,
InGroup<SwiftNameAttribute>;
def warn_attr_swift_name_num_params
: Warning<"too %select{few|many}0 parameters in %1 attribute (expected %2; got %3)">,
InGroup<SwiftNameAttribute>;

def err_attr_swift_error_no_error_parameter : Error<
"%0 attribute can only be applied to a %select{function|method}1 with an "
"error parameter">;
Expand Down
12 changes: 12 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -1834,6 +1834,16 @@ class Sema final {
}
};

/// Do a check to make sure \p Name looks like a legal argument for the
/// swift_name attribute applied to decl \p D. Raise a diagnostic if the name
/// is invalid for the given declaration.
///
/// \p AL is used to provide caret diagnostics in case of a malformed name.
///
/// \returns true if the name is a valid swift name for \p D, false otherwise.
bool DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc,
const ParsedAttr &AL);

/// A derivative of BoundTypeDiagnoser for which the diagnostic's type
/// parameter is preceded by a 0/1 enum that is 1 if the type is sizeless.
/// For example, a diagnostic with no other parameters would generally have
Expand Down Expand Up @@ -3059,6 +3069,8 @@ class Sema final {
SpeculativeLoadHardeningAttr *
mergeSpeculativeLoadHardeningAttr(Decl *D,
const SpeculativeLoadHardeningAttr &AL);
SwiftNameAttr *mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA,
StringRef Name, bool Override);
OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D,
const AttributeCommonInfo &CI);
InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2592,6 +2592,9 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
return false;
} else if (const auto *MA = dyn_cast<MinSizeAttr>(Attr))
NewAttr = S.mergeMinSizeAttr(D, *MA);
else if (const auto *SNA = dyn_cast<SwiftNameAttr>(Attr))
NewAttr = S.mergeSwiftNameAttr(D, *SNA, SNA->getName(),
AMK == Sema::AMK_Override);
else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr))
NewAttr = S.mergeOptimizeNoneAttr(D, *OA);
else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr))
Expand Down
Loading

0 comments on commit 9bb5ecf

Please sign in to comment.