mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
1) Redesign DeclAttributes to be based around an array indexed by attribute, instead
of having a ton of ad-hoc bools in it. This allows us to consolidate a ton of boilerplate, eliminating 250 lines of code: 17 files changed, 435 insertions(+), 662 deletions(-) 2) This eliminates the special case for weak and unowned attributes, which previously didn't show up in Attr.def. 3) While we're at it, keep track of proper source locations for each attribute, and use these to emit diagnostics pointing at the attribute in question instead of at a funcdecl or the @ sign. 4) Fix axle attributes, which had vertex and fragment swapped. Swift SVN r9263
This commit is contained in:
@@ -41,6 +41,8 @@ ATTR(iboutlet)
|
||||
ATTR(ibaction)
|
||||
ATTR(local_storage)
|
||||
ATTR(transparent)
|
||||
ATTR(weak)
|
||||
ATTR(unowned)
|
||||
|
||||
// SIL-specific attributes
|
||||
ATTR(sil_self)
|
||||
|
||||
@@ -99,6 +99,8 @@ public:
|
||||
/// defining a resilient structure need not actually use resilience
|
||||
/// boundaries.
|
||||
enum class Resilience : unsigned char {
|
||||
Default,
|
||||
|
||||
/// Inherently fragile language structures are not only resilient,
|
||||
/// but they have never been exposed as resilient. This permits
|
||||
/// certain kinds of optimizations that are not otherwise possible
|
||||
@@ -114,115 +116,119 @@ enum class Resilience : unsigned char {
|
||||
Resilient
|
||||
};
|
||||
|
||||
class ResilienceData {
|
||||
unsigned Valid : 1;
|
||||
unsigned Kind : 2;
|
||||
|
||||
public:
|
||||
ResilienceData() : Valid(false) {}
|
||||
ResilienceData(Resilience resil) : Valid(true), Kind(unsigned(resil)) {}
|
||||
|
||||
bool isValid() const { return Valid; }
|
||||
Resilience getResilience() const {
|
||||
assert(Valid);
|
||||
return Resilience(Kind);
|
||||
}
|
||||
};
|
||||
|
||||
enum class AbstractCC : unsigned char;
|
||||
|
||||
// Define enumerators for each attribute, e.g. AK_weak.
|
||||
#define MAKE_ENUMERATOR(id) id,
|
||||
enum AttrKind {
|
||||
#define ATTR(X) AK_##X,
|
||||
#include "swift/AST/Attr.def"
|
||||
AK_Count
|
||||
};
|
||||
|
||||
/// DeclAttributes - These are attributes that may be applied to declarations.
|
||||
class DeclAttributes {
|
||||
// Get a SourceLoc for every possible attribute that can be parsed in source.
|
||||
// the presence of the attribute is indicated by its location being set.
|
||||
SourceLoc AttrLocs[AK_Count];
|
||||
bool HasAttr[AK_Count] = { false };
|
||||
public:
|
||||
/// AtLoc - This is the location of the first '@' in the attribute specifier.
|
||||
/// If this is an empty attribute specifier, then this will be an invalid loc.
|
||||
SourceLoc AtLoc;
|
||||
|
||||
ResilienceData Resilience;
|
||||
StringRef AsmName;
|
||||
bool InOut = false;
|
||||
bool AutoClosure = false;
|
||||
bool Thin = false;
|
||||
bool NoReturn = false;
|
||||
bool Assignment = false;
|
||||
bool Conversion = false;
|
||||
bool Transparent = false;
|
||||
bool ObjC = false;
|
||||
bool ObjCBlock = false;
|
||||
bool ExplicitPrefix = false;
|
||||
bool ExplicitPostfix = false;
|
||||
bool ExplicitInfix = false;
|
||||
bool IBOutlet = false;
|
||||
bool IBAction = false;
|
||||
bool ClassProtocol = false;
|
||||
bool Weak = false;
|
||||
bool Unowned = false;
|
||||
bool LocalStorage = false;
|
||||
bool Exported = false;
|
||||
|
||||
Optional<AbstractCC> cc = Nothing;
|
||||
bool SILSelf = false;
|
||||
KernelOrShaderKind KernelOrShader = KernelOrShaderKind::Default;
|
||||
|
||||
DeclAttributes() {}
|
||||
|
||||
bool isValid() const { return AtLoc.isValid(); }
|
||||
|
||||
ResilienceData getResilienceData() const { return Resilience; }
|
||||
bool isInOut() const { return InOut; }
|
||||
bool isAutoClosure() const { return AutoClosure; }
|
||||
bool isThin() const { return Thin; }
|
||||
bool isNoReturn() const { return NoReturn; }
|
||||
bool isAssignment() const { return Assignment; }
|
||||
bool isConversion() const { return Conversion; }
|
||||
bool isTransparent() const { return Transparent; }
|
||||
bool isPrefix() const { return ExplicitPrefix; }
|
||||
bool isPostfix() const { return ExplicitPostfix; }
|
||||
bool isInfix() const { return ExplicitInfix; }
|
||||
bool isObjC() const { return ObjC; }
|
||||
bool isObjCBlock() const { return ObjCBlock; }
|
||||
bool isIBOutlet() const { return IBOutlet; }
|
||||
bool isIBAction() const { return IBAction; }
|
||||
bool isClassProtocol() const { return ClassProtocol; }
|
||||
bool isLocalStorage() const { return LocalStorage; }
|
||||
bool isWeak() const { return Weak; }
|
||||
bool isUnowned() const { return Unowned; }
|
||||
bool hasOwnership() const { return Weak || Unowned; }
|
||||
Ownership getOwnership() const {
|
||||
if (Weak) return Ownership::Weak;
|
||||
if (Unowned) return Ownership::Unowned;
|
||||
return Ownership::Strong;
|
||||
void clearAttribute(AttrKind A) {
|
||||
AttrLocs[A] = SourceLoc();
|
||||
HasAttr[A] = false;
|
||||
}
|
||||
bool isExported() const { return Exported; }
|
||||
|
||||
bool has(AttrKind A) const {
|
||||
return HasAttr[A];
|
||||
}
|
||||
|
||||
SourceLoc getLoc(AttrKind A) const {
|
||||
return AttrLocs[A];
|
||||
}
|
||||
|
||||
void setAttr(AttrKind A, SourceLoc L) {
|
||||
AttrLocs[A] = L;
|
||||
HasAttr[A] = true;
|
||||
}
|
||||
|
||||
|
||||
// This attribute list is empty if no attributes are specified. Note that
|
||||
// the presence of the leading @ is not enough to tell, because we want
|
||||
// clients to be able to remove attributes they process until they get to
|
||||
// an empty list.
|
||||
bool empty() const {
|
||||
for (bool elt : HasAttr)
|
||||
if (elt) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isInOut() const { return has(AK_inout); }
|
||||
bool isAutoClosure() const { return has(AK_auto_closure); }
|
||||
bool isThin() const { return has(AK_thin); }
|
||||
bool isNoReturn() const { return has(AK_noreturn); }
|
||||
bool isAssignment() const { return has(AK_assignment); }
|
||||
bool isConversion() const { return has(AK_conversion); }
|
||||
bool isTransparent() const {return has(AK_transparent);}
|
||||
bool isPrefix() const { return has(AK_prefix); }
|
||||
bool isPostfix() const { return has(AK_postfix); }
|
||||
bool isInfix() const { return has(AK_infix); }
|
||||
bool isObjC() const { return has(AK_objc); }
|
||||
bool isObjCBlock() const { return has(AK_objc_block); }
|
||||
bool isIBOutlet() const { return has(AK_iboutlet); }
|
||||
bool isIBAction() const { return has(AK_ibaction); }
|
||||
bool isClassProtocol() const { return has(AK_class_protocol); }
|
||||
bool isLocalStorage() const { return has(AK_local_storage); }
|
||||
bool isWeak() const { return has(AK_weak); }
|
||||
bool isUnowned() const { return has(AK_unowned); }
|
||||
bool isExported() const { return has(AK_exported); }
|
||||
bool isSILSelf() const { return has(AK_sil_self); }
|
||||
bool isKernel() const { return has(AK_kernel); }
|
||||
bool isVertex() const { return has(AK_vertex); }
|
||||
bool isFragment() const { return has(AK_fragment); }
|
||||
|
||||
bool hasCC() const { return cc.hasValue(); }
|
||||
AbstractCC getAbstractCC() const { return *cc; }
|
||||
bool isSILSelf() const { return SILSelf; }
|
||||
|
||||
Resilience getResilienceKind() const {
|
||||
if (has(AK_resilient))
|
||||
return Resilience::Resilient;
|
||||
if (has(AK_fragile))
|
||||
return Resilience::Fragile;
|
||||
if (has(AK_born_fragile))
|
||||
return Resilience::InherentlyFragile;
|
||||
return Resilience::Default;
|
||||
}
|
||||
|
||||
|
||||
bool hasOwnership() const { return isWeak() || isUnowned(); }
|
||||
Ownership getOwnership() const {
|
||||
if (isWeak()) return Ownership::Weak;
|
||||
if (isUnowned()) return Ownership::Unowned;
|
||||
return Ownership::Strong;
|
||||
}
|
||||
|
||||
KernelOrShaderKind getKernelOrShaderKind() const {
|
||||
return KernelOrShader;
|
||||
}
|
||||
bool isKernel() const {
|
||||
return KernelOrShader == KernelOrShaderKind::Kernel;
|
||||
}
|
||||
bool isVertex() const {
|
||||
return KernelOrShader == KernelOrShaderKind::Vertex;
|
||||
}
|
||||
bool isFragment() const {
|
||||
return KernelOrShader == KernelOrShaderKind::Fragment;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return !isInfix() && !getResilienceData().isValid() && !isInOut() &&
|
||||
!isAutoClosure() && !isThin() && !isNoReturn() && !isAssignment() &&
|
||||
!isConversion() && !isTransparent() && !isPostfix() && !isPrefix() &&
|
||||
!isObjC() && !isObjCBlock() && !isIBOutlet() && !isIBAction() &&
|
||||
!isClassProtocol() && !hasCC() && !hasOwnership() &&
|
||||
!isLocalStorage() && !isExported() && AsmName.empty() &&
|
||||
!isSILSelf() &&
|
||||
getKernelOrShaderKind() == KernelOrShaderKind::Default;
|
||||
if (isKernel()) return KernelOrShaderKind::Kernel;
|
||||
if (isVertex()) return KernelOrShaderKind::Fragment;
|
||||
if (isFragment()) return KernelOrShaderKind::Vertex;
|
||||
return KernelOrShaderKind::Default;
|
||||
}
|
||||
|
||||
void clearOwnership() {
|
||||
Weak = Unowned = false;
|
||||
clearAttribute(AK_weak);
|
||||
clearAttribute(AK_unowned);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -781,8 +781,8 @@ ERROR(cannot_combine_attribute,attribute_parsing,none,
|
||||
ERROR(expected_in_attribute_list,attribute_parsing,none,
|
||||
"expected ']' or ',' in attribute list", ())
|
||||
ERROR(invalid_attribute_for_lang,attribute_parsing,none,
|
||||
"attribute '%0' is only valid in language mode '%select{axle}1'",
|
||||
(StringRef, unsigned))
|
||||
"attribute is only valid in language mode '%select{axle}0'",
|
||||
(unsigned))
|
||||
|
||||
ERROR(expected_decl_attribute_not_type,attribute_parsing,none,
|
||||
"expected declaration attribute, not a type attribute", ())
|
||||
@@ -1082,7 +1082,7 @@ ERROR(class_protocol_not_protocol,sema_tcd,none,
|
||||
"'class_protocol' attribute can only be applied to protocols", ())
|
||||
|
||||
ERROR(invalid_decl_attribute,sema_tcd,none,
|
||||
"attribute '%0' cannot be applied to declaration", (StringRef))
|
||||
"attribute cannot be applied to declaration", ())
|
||||
|
||||
// Extensions
|
||||
ERROR(non_nominal_extension,sema_tcd,none,
|
||||
|
||||
@@ -178,20 +178,11 @@ void PrintAST::printAttributes(const DeclAttributes &Attrs) {
|
||||
AP.next() << "transparent";
|
||||
if (Attrs.isInfix())
|
||||
AP.next() << "infix";
|
||||
if (Attrs.getResilienceData().isValid()) {
|
||||
switch (Attrs.getResilienceData().getResilience()) {
|
||||
case Resilience::Fragile:
|
||||
AP.next() << "fragile";
|
||||
break;
|
||||
|
||||
case Resilience::InherentlyFragile:
|
||||
AP.next() << "born_fragile";
|
||||
break;
|
||||
|
||||
case Resilience::Resilient:
|
||||
AP.next() << "resilient";
|
||||
break;
|
||||
}
|
||||
switch (Attrs.getResilienceKind()) {
|
||||
case Resilience::Default: break;
|
||||
case Resilience::Fragile: AP.next() << "fragile"; break;
|
||||
case Resilience::InherentlyFragile: AP.next() << "born_fragile"; break;
|
||||
case Resilience::Resilient: AP.next() << "resilient"; break;
|
||||
}
|
||||
if (Attrs.isInOut())
|
||||
AP.next() << "inout";
|
||||
|
||||
@@ -90,13 +90,12 @@ void AttributedTypeRepr::printAttrs(llvm::raw_ostream &OS) const {
|
||||
const DeclAttributes &Attrs = getAttrs();
|
||||
llvm::SmallString<64> AttrStr;
|
||||
llvm::raw_svector_ostream AttrOS(AttrStr);
|
||||
if (Attrs.Resilience.isValid()) {
|
||||
switch (Attrs.Resilience.getResilience()) {
|
||||
switch (Attrs.getResilienceKind()) {
|
||||
case Resilience::Default: break;
|
||||
case Resilience::InherentlyFragile: AttrOS << "born_fragile,"; break;
|
||||
case Resilience::Fragile: AttrOS << "fragile,"; break;
|
||||
case Resilience::Resilient: AttrOS << "resilient,"; break;
|
||||
}
|
||||
}
|
||||
if (!Attrs.AsmName.empty())
|
||||
AttrOS << "asmname=\"" << Attrs.AsmName << "\",";
|
||||
if (Attrs.isInOut()) AttrOS << "inout,";
|
||||
|
||||
@@ -290,7 +290,8 @@ namespace {
|
||||
}
|
||||
|
||||
Decl *
|
||||
VisitUnresolvedUsingTypenameDecl(const clang::UnresolvedUsingTypenameDecl *decl) {
|
||||
VisitUnresolvedUsingTypenameDecl(const
|
||||
clang::UnresolvedUsingTypenameDecl *decl) {
|
||||
// Note: only occurs in templates.
|
||||
return nullptr;
|
||||
}
|
||||
@@ -831,7 +832,7 @@ namespace {
|
||||
|
||||
// Handle attributes.
|
||||
if (decl->hasAttr<clang::IBOutletAttr>())
|
||||
result->getMutableAttrs().IBOutlet = true;
|
||||
result->getMutableAttrs().setAttr(AK_iboutlet, SourceLoc());
|
||||
// FIXME: Handle IBOutletCollection.
|
||||
|
||||
return result;
|
||||
@@ -917,7 +918,8 @@ namespace {
|
||||
return VisitObjCMethodDecl(decl, dc);
|
||||
}
|
||||
|
||||
Decl *VisitObjCMethodDecl(const clang::ObjCMethodDecl *decl, DeclContext *dc) {
|
||||
Decl *VisitObjCMethodDecl(const clang::ObjCMethodDecl *decl,
|
||||
DeclContext *dc) {
|
||||
auto loc = Impl.importSourceLoc(decl->getLocStart());
|
||||
|
||||
// The name of the method is the first part of the selector.
|
||||
@@ -989,7 +991,7 @@ namespace {
|
||||
setVarDeclContexts(bodyPatterns, result);
|
||||
|
||||
// Mark this as an Objective-C method.
|
||||
result->getMutableAttrs().ObjC = true;
|
||||
result->getMutableAttrs().setAttr(AK_objc, SourceLoc());
|
||||
result->setIsObjC(true);
|
||||
|
||||
// Mark class methods as static.
|
||||
@@ -1034,7 +1036,7 @@ namespace {
|
||||
|
||||
// Handle attributes.
|
||||
if (decl->hasAttr<clang::IBActionAttr>())
|
||||
result->getMutableAttrs().IBAction = true;
|
||||
result->getMutableAttrs().setAttr(AK_ibaction, SourceLoc());
|
||||
|
||||
// Check whether there's some special method to import.
|
||||
result->setClangNode(decl);
|
||||
@@ -1975,8 +1977,8 @@ namespace {
|
||||
result->setCheckedInheritanceClause();
|
||||
|
||||
// Note that this is an Objective-C and class protocol.
|
||||
result->getMutableAttrs().ObjC = true;
|
||||
result->getMutableAttrs().ClassProtocol = true;
|
||||
result->getMutableAttrs().setAttr(AK_objc, SourceLoc());
|
||||
result->getMutableAttrs().setAttr(AK_class_protocol, SourceLoc());
|
||||
result->setIsObjC(true);
|
||||
|
||||
// Add the implicit 'Self' associated type.
|
||||
@@ -2049,7 +2051,7 @@ namespace {
|
||||
result->setCheckedInheritanceClause();
|
||||
|
||||
// Note that this is an Objective-C class.
|
||||
result->getMutableAttrs().ObjC = true;
|
||||
result->getMutableAttrs().setAttr(AK_objc, SourceLoc());
|
||||
result->setIsObjC(true);
|
||||
|
||||
// Import each of the members.
|
||||
@@ -2160,12 +2162,11 @@ namespace {
|
||||
|
||||
// Handle attributes.
|
||||
if (decl->hasAttr<clang::IBOutletAttr>())
|
||||
result->getMutableAttrs().IBOutlet = true;
|
||||
result->getMutableAttrs().setAttr(AK_iboutlet, SourceLoc());
|
||||
// FIXME: Handle IBOutletCollection.
|
||||
|
||||
if (overridden) {
|
||||
if (overridden)
|
||||
result->setOverriddenDecl(overridden);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -2233,7 +2234,8 @@ namespace {
|
||||
}
|
||||
|
||||
/// \brief Classify the given Clang enumeration to describe how it
|
||||
EnumKind ClangImporter::Implementation::classifyEnum(const clang::EnumDecl *decl) {
|
||||
EnumKind ClangImporter::Implementation::
|
||||
classifyEnum(const clang::EnumDecl *decl) {
|
||||
Identifier name;
|
||||
if (decl->getDeclName())
|
||||
name = importName(decl->getDeclName());
|
||||
@@ -2275,8 +2277,8 @@ Decl *ClangImporter::Implementation::importDecl(const clang::NamedDecl *decl) {
|
||||
}
|
||||
|
||||
Decl *
|
||||
ClangImporter::Implementation::importMirroredDecl(const clang::ObjCMethodDecl *decl,
|
||||
DeclContext *dc) {
|
||||
ClangImporter::Implementation::
|
||||
importMirroredDecl(const clang::ObjCMethodDecl *decl, DeclContext *dc) {
|
||||
if (!decl)
|
||||
return nullptr;
|
||||
|
||||
|
||||
@@ -1358,7 +1358,7 @@ ClassDecl *IRGenModule::getSwiftRootClass() {
|
||||
/*generics*/ nullptr,
|
||||
Context.TheBuiltinModule);
|
||||
SwiftRootClass->computeType();
|
||||
SwiftRootClass->getMutableAttrs().ObjC = true;
|
||||
SwiftRootClass->getMutableAttrs().setAttr(AK_objc, SourceLoc());
|
||||
SwiftRootClass->setIsObjC(true);
|
||||
return SwiftRootClass;
|
||||
}
|
||||
|
||||
@@ -98,29 +98,11 @@ bool Parser::parseTopLevel() {
|
||||
return FoundTopLevelCodeToExecute;
|
||||
}
|
||||
|
||||
namespace {
|
||||
#define MAKE_ENUMERATOR(id) id,
|
||||
enum class AttrName {
|
||||
none,
|
||||
#define ATTR(X) X,
|
||||
static AttrKind getAttrName(StringRef text) {
|
||||
return llvm::StringSwitch<AttrKind>(text)
|
||||
#define ATTR(X) .Case(#X, AK_##X)
|
||||
#include "swift/AST/Attr.def"
|
||||
};
|
||||
}
|
||||
|
||||
static AttrName getAttrName(StringRef text) {
|
||||
return llvm::StringSwitch<AttrName>(text)
|
||||
#define ATTR(X) .Case(#X, AttrName::X)
|
||||
#include "swift/AST/Attr.def"
|
||||
.Default(AttrName::none);
|
||||
}
|
||||
|
||||
static Resilience getResilience(AttrName attr) {
|
||||
switch (attr) {
|
||||
case AttrName::resilient: return Resilience::Resilient;
|
||||
case AttrName::fragile: return Resilience::Fragile;
|
||||
case AttrName::born_fragile: return Resilience::InherentlyFragile;
|
||||
default: llvm_unreachable("bad resilience");
|
||||
}
|
||||
.Default(AK_Count);
|
||||
}
|
||||
|
||||
/// \verbatim
|
||||
@@ -137,35 +119,18 @@ static Resilience getResilience(AttrName attr) {
|
||||
/// \endverbatim
|
||||
bool Parser::parseAttribute(DeclAttributes &Attributes, unsigned KindMask,
|
||||
bool OldStyle) {
|
||||
if (Tok.is(tok::kw_weak)) {
|
||||
auto Loc = consumeToken(tok::kw_weak);
|
||||
|
||||
if (Attributes.hasOwnership())
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
else
|
||||
Attributes.Weak = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Tok.is(tok::kw_unowned)) {
|
||||
auto Loc = consumeToken(tok::kw_unowned);
|
||||
if (Attributes.hasOwnership())
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
else
|
||||
Attributes.Unowned = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Tok.is(tok::identifier)) {
|
||||
// If this not an identifier, the attribute is malformed.
|
||||
if (Tok.isNot(tok::identifier) &&
|
||||
Tok.isNot(tok::kw_weak) &&
|
||||
Tok.isNot(tok::kw_unowned)) {
|
||||
diagnose(Tok, diag::expected_attribute_name);
|
||||
if (OldStyle) skipUntil(tok::r_square);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (AttrName attr = getAttrName(Tok.getText())) {
|
||||
case AttrName::none:
|
||||
// Determine which attribute it is, and diagnose it if unknown.
|
||||
AttrKind attr = getAttrName(Tok.getText());
|
||||
if (attr == AK_Count) {
|
||||
diagnose(Tok, diag::unknown_attribute, Tok.getText());
|
||||
if (OldStyle)
|
||||
skipUntil(tok::r_square);
|
||||
@@ -182,66 +147,55 @@ bool Parser::parseAttribute(DeclAttributes &Attributes, unsigned KindMask,
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
// Infix attributes.
|
||||
case AttrName::infix: {
|
||||
auto Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.isInfix())
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
else
|
||||
Attributes.ExplicitInfix = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// SIL's 'local_storage' type attribute.
|
||||
case AttrName::local_storage: {
|
||||
auto Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.isLocalStorage())
|
||||
// Ok, it is a valid attribute, eat it, and then process it.
|
||||
SourceLoc Loc = consumeToken();
|
||||
|
||||
// Diagnose duplicated attributes.
|
||||
if (Attributes.has(attr))
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
else if (!isInSILMode())
|
||||
else
|
||||
Attributes.setAttr(attr, Loc);
|
||||
|
||||
// Handle any attribute-specific processing logic.
|
||||
switch (attr) {
|
||||
default: break;
|
||||
case AK_local_storage:
|
||||
case AK_sil_self:
|
||||
if (!isInSILMode()) // SIL's 'local_storage' type attribute.
|
||||
diagnose(Loc, diag::only_allowed_in_sil, "local_storage");
|
||||
else
|
||||
Attributes.LocalStorage = true;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
// SIL's 'sil_self' type attribute.
|
||||
case AttrName::sil_self: {
|
||||
auto Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.isSILSelf())
|
||||
// Ownership attributes.
|
||||
case AK_weak:
|
||||
case AK_unowned:
|
||||
// Test for duplicate entries by temporarily removing this one.
|
||||
Attributes.clearAttribute(attr);
|
||||
if (Attributes.hasOwnership()) {
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
else if (!isInSILMode())
|
||||
diagnose(Loc, diag::only_allowed_in_sil, "sil_self");
|
||||
else
|
||||
Attributes.SILSelf = true;
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
Attributes.setAttr(attr, Loc);
|
||||
break;
|
||||
|
||||
|
||||
// Resilience attributes.
|
||||
case AttrName::resilient:
|
||||
case AttrName::fragile:
|
||||
case AttrName::born_fragile: {
|
||||
auto Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.Resilience.isValid())
|
||||
case AK_resilient:
|
||||
case AK_fragile:
|
||||
case AK_born_fragile:
|
||||
// Test for duplicate entries by temporarily removing this one.
|
||||
Attributes.clearAttribute(attr);
|
||||
if (Attributes.getResilienceKind() != Resilience::Default) {
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
else {
|
||||
Resilience resil = getResilience(attr);
|
||||
// TODO: 'fragile' should allow deployment versioning.
|
||||
Attributes.Resilience = ResilienceData(resil);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
Attributes.setAttr(attr, Loc);
|
||||
break;
|
||||
|
||||
// 'inout' attribute.
|
||||
// FIXME: only permit this in specific contexts.
|
||||
case AttrName::inout: {
|
||||
SourceLoc TokLoc = consumeToken(tok::identifier);
|
||||
if (Attributes.InOut)
|
||||
diagnose(Tok, diag::duplicate_attribute);
|
||||
|
||||
Attributes.InOut = true;
|
||||
|
||||
case AK_inout: {
|
||||
// Permit "qualifiers" on the inout.
|
||||
SourceLoc beginLoc = Tok.getLoc();
|
||||
if (consumeIfNotAtStartOfLine(tok::l_paren)) {
|
||||
@@ -255,19 +209,26 @@ bool Parser::parseAttribute(DeclAttributes &Attributes, unsigned KindMask,
|
||||
// Verify that we're not combining this attribute incorrectly. Cannot be
|
||||
// both inout and auto_closure.
|
||||
if (Attributes.isAutoClosure()) {
|
||||
diagnose(TokLoc, diag::cannot_combine_attribute, "auto_closure");
|
||||
Attributes.AutoClosure = false;
|
||||
diagnose(Loc, diag::cannot_combine_attribute, "auto_closure");
|
||||
Attributes.clearAttribute(attr);
|
||||
}
|
||||
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
// FIXME: Only valid on var and tuple elements, not on func's, typealias, etc.
|
||||
case AK_auto_closure:
|
||||
if (Attributes.isInOut()) {
|
||||
// Verify that we're not combining this attribute incorrectly. Cannot be
|
||||
// both inout and auto_closure.
|
||||
diagnose(Loc, diag::cannot_combine_attribute, "inout");
|
||||
Attributes.clearAttribute(attr);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
// 'cc' attribute.
|
||||
// FIXME: only permit this in type contexts.
|
||||
case AttrName::cc: {
|
||||
auto Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.hasCC())
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
case AK_cc: {
|
||||
|
||||
// Parse the cc name in parens.
|
||||
SourceLoc beginLoc = Tok.getLoc(), nameLoc, endLoc;
|
||||
@@ -309,158 +270,30 @@ bool Parser::parseAttribute(DeclAttributes &Attributes, unsigned KindMask,
|
||||
return false;
|
||||
}
|
||||
|
||||
case AttrName::class_protocol: {
|
||||
auto Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.isClassProtocol())
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
|
||||
|
||||
Attributes.ClassProtocol = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 'objc_block' attribute.
|
||||
// FIXME: only permit this in type contexts.
|
||||
case AttrName::objc_block: {
|
||||
auto Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.ObjCBlock)
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
|
||||
Attributes.ObjCBlock = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: Only valid on var and tuple elements, not on func's, typealias, etc.
|
||||
case AttrName::auto_closure: {
|
||||
SourceLoc Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.isAutoClosure())
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
else if (Attributes.isInOut()) {
|
||||
// Verify that we're not combining this attribute incorrectly. Cannot be
|
||||
// both inout and auto_closure.
|
||||
diagnose(Loc, diag::cannot_combine_attribute, "inout");
|
||||
} else {
|
||||
Attributes.AutoClosure = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case AttrName::thin: {
|
||||
auto Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.isThin())
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
else
|
||||
Attributes.Thin = true;
|
||||
return false;
|
||||
}
|
||||
case AttrName::noreturn: {
|
||||
auto Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.isNoReturn())
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
else
|
||||
Attributes.NoReturn = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
case AttrName::assignment: {
|
||||
auto Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.isAssignment())
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
|
||||
Attributes.Assignment = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
case AttrName::prefix: {
|
||||
auto Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.isPrefix())
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
else if (Attributes.isPostfix())
|
||||
case AK_prefix:
|
||||
if (Attributes.isPostfix()) {
|
||||
diagnose(Loc, diag::cannot_combine_attribute, "postfix");
|
||||
else
|
||||
Attributes.ExplicitPrefix = true;
|
||||
return false;
|
||||
Attributes.clearAttribute(attr);
|
||||
}
|
||||
break;
|
||||
|
||||
case AttrName::postfix: {
|
||||
SourceLoc Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.isPostfix())
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
else if (Attributes.isPrefix())
|
||||
case AK_postfix:
|
||||
if (Attributes.isPrefix()) {
|
||||
diagnose(Loc, diag::cannot_combine_attribute, "prefix");
|
||||
else
|
||||
Attributes.ExplicitPostfix = true;
|
||||
return false;
|
||||
Attributes.clearAttribute(attr);
|
||||
}
|
||||
break;
|
||||
|
||||
case AttrName::conversion: {
|
||||
auto Loc = consumeToken(tok::identifier);
|
||||
if (Attributes.isConversion())
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
else
|
||||
Attributes.Conversion = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
case AttrName::exported: {
|
||||
if (Attributes.isExported())
|
||||
diagnose(Tok, diag::duplicate_attribute);
|
||||
consumeToken(tok::identifier);
|
||||
|
||||
Attributes.Exported = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
case AttrName::transparent: {
|
||||
if (Attributes.isTransparent())
|
||||
diagnose(Tok, diag::duplicate_attribute);
|
||||
consumeToken(tok::identifier);
|
||||
|
||||
Attributes.Transparent = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
case AttrName::iboutlet: {
|
||||
if (Attributes.isIBOutlet())
|
||||
diagnose(Tok, diag::duplicate_attribute);
|
||||
|
||||
consumeToken(tok::identifier);
|
||||
Attributes.IBOutlet = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
case AttrName::ibaction: {
|
||||
if (Attributes.isIBAction())
|
||||
diagnose(Tok, diag::duplicate_attribute);
|
||||
|
||||
consumeToken(tok::identifier);
|
||||
Attributes.IBAction = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
case AttrName::objc: {
|
||||
if (Attributes.isObjC())
|
||||
diagnose(Tok, diag::duplicate_attribute);
|
||||
|
||||
consumeToken(tok::identifier);
|
||||
Attributes.ObjC = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// FIXME: This is a temporary hack until we can import C modules.
|
||||
case AttrName::asmname: {
|
||||
SourceLoc TokLoc = Tok.getLoc();
|
||||
if (!Attributes.AsmName.empty())
|
||||
diagnose(Tok, diag::duplicate_attribute);
|
||||
consumeToken(tok::identifier);
|
||||
|
||||
case AK_asmname: {
|
||||
if (!consumeIf(tok::equal)) {
|
||||
diagnose(TokLoc, diag::asmname_expected_equals);
|
||||
diagnose(Loc, diag::asmname_expected_equals);
|
||||
Attributes.clearAttribute(attr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Tok.is(tok::string_literal)) {
|
||||
diagnose(TokLoc, diag::asmname_expected_string_literal);
|
||||
if (Tok.isNot(tok::string_literal)) {
|
||||
diagnose(Loc, diag::asmname_expected_string_literal);
|
||||
Attributes.clearAttribute(attr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -468,7 +301,8 @@ bool Parser::parseAttribute(DeclAttributes &Attributes, unsigned KindMask,
|
||||
L->getStringLiteralSegments(Tok, Segments);
|
||||
if (Segments.size() != 1 ||
|
||||
Segments.front().Kind == Lexer::StringSegment::Expr) {
|
||||
diagnose(TokLoc, diag::asmname_interpolated_string);
|
||||
diagnose(Loc, diag::asmname_interpolated_string);
|
||||
Attributes.clearAttribute(attr);
|
||||
} else {
|
||||
Attributes.AsmName = StringRef(
|
||||
SourceMgr->getMemoryBuffer(BufferID)->getBufferStart() +
|
||||
@@ -476,68 +310,31 @@ bool Parser::parseAttribute(DeclAttributes &Attributes, unsigned KindMask,
|
||||
Segments.front().Length);
|
||||
}
|
||||
consumeToken(tok::string_literal);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
case AttrName::kernel: {
|
||||
case AK_kernel:
|
||||
case AK_vertex:
|
||||
case AK_fragment:
|
||||
// Reject Axle specific attributes in non-axle mode.
|
||||
if (!Context.LangOpts.Axle) {
|
||||
diagnose(Tok, diag::invalid_attribute_for_lang, Tok.getText(),
|
||||
diagnose(Loc, diag::invalid_attribute_for_lang,
|
||||
0 /* axle */);
|
||||
consumeToken(tok::identifier);
|
||||
return false;
|
||||
}
|
||||
if (Attributes.isKernel())
|
||||
diagnose(Tok, diag::duplicate_attribute);
|
||||
if (Attributes.isVertex())
|
||||
diagnose(Tok, diag::cannot_combine_attribute, "vertex");
|
||||
if (Attributes.isFragment())
|
||||
diagnose(Tok, diag::cannot_combine_attribute, "fragment");
|
||||
|
||||
consumeToken(tok::identifier);
|
||||
Attributes.KernelOrShader = KernelOrShaderKind::Kernel;
|
||||
Attributes.clearAttribute(attr);
|
||||
return false;
|
||||
}
|
||||
|
||||
case AttrName::vertex: {
|
||||
if (!Context.LangOpts.Axle) {
|
||||
diagnose(Tok, diag::invalid_attribute_for_lang, Tok.getText(),
|
||||
0 /* axle */);
|
||||
consumeToken(tok::identifier);
|
||||
return false;
|
||||
// Check multiple specifications by temporarily removing this attribute.
|
||||
Attributes.clearAttribute(attr);
|
||||
if (Attributes.getKernelOrShaderKind() != KernelOrShaderKind::Default) {
|
||||
diagnose(Loc, diag::duplicate_attribute);
|
||||
break;
|
||||
}
|
||||
if (Attributes.isVertex())
|
||||
diagnose(Tok, diag::duplicate_attribute);
|
||||
if (Attributes.isKernel())
|
||||
diagnose(Tok, diag::cannot_combine_attribute, "kernel");
|
||||
if (Attributes.isFragment())
|
||||
diagnose(Tok, diag::cannot_combine_attribute, "fragment");
|
||||
|
||||
consumeToken(tok::identifier);
|
||||
Attributes.KernelOrShader = KernelOrShaderKind::Vertex;
|
||||
return false;
|
||||
Attributes.setAttr(attr, Loc);
|
||||
break;
|
||||
}
|
||||
|
||||
case AttrName::fragment: {
|
||||
if (!Context.LangOpts.Axle) {
|
||||
diagnose(Tok, diag::invalid_attribute_for_lang, Tok.getText(),
|
||||
0 /* axle */);
|
||||
consumeToken(tok::identifier);
|
||||
return false;
|
||||
}
|
||||
if (Attributes.isFragment())
|
||||
diagnose(Tok, diag::duplicate_attribute);
|
||||
if (Attributes.isKernel())
|
||||
diagnose(Tok, diag::cannot_combine_attribute, "kernel");
|
||||
if (Attributes.isVertex())
|
||||
diagnose(Tok, diag::cannot_combine_attribute, "vertex");
|
||||
|
||||
consumeToken(tok::identifier);
|
||||
Attributes.KernelOrShader = KernelOrShaderKind::Fragment;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
llvm_unreachable("bad attribute kind");
|
||||
}
|
||||
|
||||
/// \brief This is the internal implementation of \c parseAttributeList, which
|
||||
@@ -799,15 +596,11 @@ ParserResult<ImportDecl> Parser::parseDeclImport(unsigned Flags,
|
||||
DeclAttributes &Attributes) {
|
||||
SourceLoc ImportLoc = consumeToken(tok::kw_import);
|
||||
|
||||
bool Exported;
|
||||
{
|
||||
parseAttributeList(Attributes, AK_DeclAttributes, true);
|
||||
|
||||
Exported = Attributes.isExported();
|
||||
Attributes.Exported = false;
|
||||
bool Exported = Attributes.isExported();
|
||||
Attributes.clearAttribute(AK_exported);
|
||||
if (!Attributes.empty())
|
||||
diagnose(Attributes.AtLoc, diag::import_attributes);
|
||||
}
|
||||
|
||||
if (!(Flags & PD_AllowTopLevel)) {
|
||||
diagnose(ImportLoc, diag::decl_inner_scope);
|
||||
|
||||
@@ -625,13 +625,14 @@ bool SILParser::parseSILType(SILType &Result) {
|
||||
P.parseAttributeList(attrs, Parser::AK_SILAttributes, false);
|
||||
P.parseAttributeList(attrs, Parser::AK_SILAttributes, true);
|
||||
|
||||
// Handle [local_storage], which changes the SIL value category.
|
||||
// Handle @local_storage, which changes the SIL value category.
|
||||
if (attrs.isLocalStorage()) {
|
||||
// Require '*' on local_storage values.
|
||||
if (category != SILValueCategory::Address)
|
||||
P.diagnose(attrs.AtLoc, diag::sil_local_storage_non_address);
|
||||
P.diagnose(attrs.getLoc(AK_local_storage),
|
||||
diag::sil_local_storage_non_address);
|
||||
category = SILValueCategory::LocalStorage;
|
||||
attrs.LocalStorage = false;
|
||||
attrs.clearAttribute(AK_local_storage);
|
||||
}
|
||||
|
||||
// Parse Generic Parameters. Generic Parameters are visible in the function
|
||||
@@ -665,7 +666,8 @@ bool SILParser::parseSILType(SILType &Result) {
|
||||
P.Context);
|
||||
Ty.setType(resultType);
|
||||
// Reset attributes that are applied.
|
||||
attrs.Thin = false;
|
||||
attrs.clearAttribute(AK_thin);
|
||||
attrs.clearAttribute(AK_cc);
|
||||
attrs.cc = Nothing;
|
||||
}
|
||||
|
||||
|
||||
@@ -1145,7 +1145,7 @@ public:
|
||||
ProtocolDecl *protocolContext = dyn_cast<ProtocolDecl>(dc);
|
||||
bool isObjC = (classContext && classContext->isObjC())
|
||||
|| (protocolContext && protocolContext->isObjC())
|
||||
|| SD->getAttrs().ObjC;
|
||||
|| SD->getAttrs().isObjC();
|
||||
if (isObjC && SD->getObjCSubscriptKind() != ObjCSubscriptKind::None) {
|
||||
SD->setIsObjC(true);
|
||||
}
|
||||
@@ -1440,32 +1440,29 @@ public:
|
||||
auto Info = AnyFunctionType::ExtInfo();
|
||||
|
||||
if (Attrs.hasCC()) {
|
||||
TC.diagnose(FD->getStartLoc(), diag::invalid_decl_attribute, "cc");
|
||||
TC.diagnose(Attrs.getLoc(AK_cc), diag::invalid_decl_attribute);
|
||||
Attrs.cc = {};
|
||||
Attrs.clearAttribute(AK_cc);
|
||||
}
|
||||
|
||||
if (Attrs.isThin()) {
|
||||
TC.diagnose(FD->getStartLoc(), diag::invalid_decl_attribute,
|
||||
"thin");
|
||||
Attrs.Thin = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_thin), diag::invalid_decl_attribute);
|
||||
Attrs.clearAttribute(AK_thin);
|
||||
}
|
||||
|
||||
// 'noreturn' is allowed on a function declaration.
|
||||
Info = Info.withIsNoReturn(Attrs.isNoReturn());
|
||||
if (consumeAttributes) {
|
||||
Attrs.NoReturn = false;
|
||||
}
|
||||
if (consumeAttributes)
|
||||
Attrs.clearAttribute(AK_noreturn);
|
||||
|
||||
if (Attrs.isAutoClosure()) {
|
||||
TC.diagnose(FD->getStartLoc(), diag::invalid_decl_attribute,
|
||||
"auto_closure");
|
||||
Attrs.AutoClosure = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_auto_closure), diag::invalid_decl_attribute);
|
||||
Attrs.clearAttribute(AK_auto_closure);
|
||||
}
|
||||
|
||||
if (Attrs.isObjCBlock()) {
|
||||
TC.diagnose(FD->getStartLoc(), diag::invalid_decl_attribute,
|
||||
"objc_block");
|
||||
Attrs.ObjCBlock = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_objc_block), diag::invalid_decl_attribute);
|
||||
Attrs.clearAttribute(AK_objc_block);
|
||||
}
|
||||
|
||||
return Info;
|
||||
@@ -1596,13 +1593,13 @@ public:
|
||||
SourceLoc insertionLoc = FD->getLoc();
|
||||
const char *insertionText;
|
||||
if (postfixOp) {
|
||||
insertionText = "[postfix] ";
|
||||
insertionText = "@postfix ";
|
||||
op = *postfixOp;
|
||||
FD->getMutableAttrs().ExplicitPostfix = true;
|
||||
FD->getMutableAttrs().setAttr(AK_postfix, SourceLoc());
|
||||
} else {
|
||||
insertionText = "[prefix] ";
|
||||
insertionText = "@prefix ";
|
||||
op = *prefixOp;
|
||||
FD->getMutableAttrs().ExplicitPrefix = true;
|
||||
FD->getMutableAttrs().setAttr(AK_prefix, SourceLoc());
|
||||
}
|
||||
|
||||
// Emit diagnostic with the Fix-It.
|
||||
@@ -2704,7 +2701,7 @@ static void validateAttributes(TypeChecker &TC, Decl *D) {
|
||||
|
||||
if (error) {
|
||||
TC.diagnose(D->getStartLoc(), *error);
|
||||
D->getMutableAttrs().ObjC = false;
|
||||
D->getMutableAttrs().clearAttribute(AK_objc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2771,8 +2768,8 @@ static void validateAttributes(TypeChecker &TC, Decl *D) {
|
||||
// FIXME: This could do some type validation as well (all IBOutlets refer
|
||||
// to objects).
|
||||
if (!(isa<VarDecl>(D) && isInClassContext(D))) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_iboutlet);
|
||||
D->getMutableAttrs().IBOutlet = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_iboutlet), diag::invalid_iboutlet);
|
||||
D->getMutableAttrs().clearAttribute(AK_iboutlet);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2782,8 +2779,8 @@ static void validateAttributes(TypeChecker &TC, Decl *D) {
|
||||
const FuncDecl *FD = dyn_cast<FuncDecl>(D);
|
||||
if (!FD || !isa<ClassDecl>(D->getDeclContext()) || FD->isStatic() ||
|
||||
FD->isGetterOrSetter()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_ibaction_decl);
|
||||
D->getMutableAttrs().IBAction = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_ibaction), diag::invalid_ibaction_decl);
|
||||
D->getMutableAttrs().clearAttribute(AK_ibaction);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2794,7 +2791,7 @@ static void validateAttributes(TypeChecker &TC, Decl *D) {
|
||||
Type ResultTy = CurriedTy->castTo<AnyFunctionType>()->getResult();
|
||||
if (!ResultTy->isEqual(TupleType::getEmpty(TC.Context))) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_ibaction_result, ResultTy);
|
||||
D->getMutableAttrs().IBAction = false;
|
||||
D->getMutableAttrs().clearAttribute(AK_ibaction);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2818,16 +2815,16 @@ static void validateAttributes(TypeChecker &TC, Decl *D) {
|
||||
if (Attrs.isPostfix()) {
|
||||
// Only operator functions can be postfix.
|
||||
if (!isOperator) {
|
||||
TC.diagnose(D->getStartLoc(), diag::postfix_not_an_operator);
|
||||
D->getMutableAttrs().ExplicitPostfix = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_postfix), diag::postfix_not_an_operator);
|
||||
D->getMutableAttrs().clearAttribute(AK_postfix);
|
||||
// FIXME: Set the 'isError' bit on the decl.
|
||||
return;
|
||||
}
|
||||
|
||||
// Only unary operators can be postfix.
|
||||
if (!FDOrNull || !FDOrNull->isUnaryOperator()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_postfix_input);
|
||||
D->getMutableAttrs().ExplicitPostfix = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_postfix), diag::invalid_postfix_input);
|
||||
D->getMutableAttrs().clearAttribute(AK_postfix);
|
||||
// FIXME: Set the 'isError' bit on the decl.
|
||||
return;
|
||||
}
|
||||
@@ -2836,16 +2833,16 @@ static void validateAttributes(TypeChecker &TC, Decl *D) {
|
||||
if (Attrs.isPrefix()) {
|
||||
// Only operator functions can be postfix.
|
||||
if (!isOperator) {
|
||||
TC.diagnose(D->getStartLoc(), diag::prefix_not_an_operator);
|
||||
D->getMutableAttrs().ExplicitPostfix = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_prefix), diag::prefix_not_an_operator);
|
||||
D->getMutableAttrs().clearAttribute(AK_prefix);
|
||||
// FIXME: Set the 'isError' bit on the decl.
|
||||
return;
|
||||
}
|
||||
|
||||
// Only unary operators can be postfix.
|
||||
if (!FDOrNull || !FDOrNull->isUnaryOperator()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_prefix_input);
|
||||
D->getMutableAttrs().ExplicitPostfix = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_prefix), diag::invalid_prefix_input);
|
||||
D->getMutableAttrs().clearAttribute(AK_prefix);
|
||||
// FIXME: Set the 'isError' bit on the decl.
|
||||
return;
|
||||
}
|
||||
@@ -2855,11 +2852,11 @@ static void validateAttributes(TypeChecker &TC, Decl *D) {
|
||||
// Only function declarations can be assignments.
|
||||
FuncDecl *FD = dyn_cast<FuncDecl>(D);
|
||||
if (!FD || !FD->isOperator()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_decl_attribute,"assignment");
|
||||
D->getMutableAttrs().Assignment = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_assignment), diag::invalid_decl_attribute);
|
||||
D->getMutableAttrs().clearAttribute(AK_assignment);
|
||||
} else if (NumArguments < 1) {
|
||||
TC.diagnose(D->getStartLoc(), diag::assignment_without_inout);
|
||||
D->getMutableAttrs().Assignment = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_assignment),diag::assignment_without_inout);
|
||||
D->getMutableAttrs().clearAttribute(AK_assignment);
|
||||
} else {
|
||||
auto FT = FD->getType()->castTo<AnyFunctionType>();
|
||||
Type ParamType = FT->getInput();
|
||||
@@ -2868,8 +2865,9 @@ static void validateAttributes(TypeChecker &TC, Decl *D) {
|
||||
ParamType = ParamTT->getElementType(0);
|
||||
|
||||
if (!ParamType->is<LValueType>()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::assignment_without_inout);
|
||||
D->getMutableAttrs().Assignment = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_assignment),
|
||||
diag::assignment_without_inout);
|
||||
D->getMutableAttrs().clearAttribute(AK_assignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2879,12 +2877,12 @@ static void validateAttributes(TypeChecker &TC, Decl *D) {
|
||||
// conversions.
|
||||
FuncDecl *FD = dyn_cast<FuncDecl>(D);
|
||||
if (!FD) {
|
||||
TC.diagnose(D->getStartLoc(), diag::conversion_not_function);
|
||||
D->getMutableAttrs().Conversion = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_conversion), diag::conversion_not_function);
|
||||
D->getMutableAttrs().clearAttribute(AK_conversion);
|
||||
} else if (!FD->isInstanceMember()) {
|
||||
TC.diagnose(FD->getStartLoc(), diag::conversion_not_instance_method,
|
||||
FD->getName());
|
||||
FD->getMutableAttrs().Conversion = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_conversion),
|
||||
diag::conversion_not_instance_method, FD->getName());
|
||||
D->getMutableAttrs().clearAttribute(AK_conversion);
|
||||
} else if (!FD->getType()->is<ErrorType>()) {
|
||||
AnyFunctionType *BoundMethodTy
|
||||
= FD->getType()->castTo<AnyFunctionType>()->getResult()
|
||||
@@ -2905,9 +2903,9 @@ static void validateAttributes(TypeChecker &TC, Decl *D) {
|
||||
}
|
||||
|
||||
if (!AcceptsEmptyParamList) {
|
||||
TC.diagnose(FD->getStartLoc(), diag::conversion_params,
|
||||
TC.diagnose(Attrs.getLoc(AK_conversion), diag::conversion_params,
|
||||
FD->getName());
|
||||
D->getMutableAttrs().Conversion = false;
|
||||
D->getMutableAttrs().clearAttribute(AK_conversion);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2918,96 +2916,72 @@ static void validateAttributes(TypeChecker &TC, Decl *D) {
|
||||
auto *ED = dyn_cast<ExtensionDecl>(D);
|
||||
|
||||
if (!AFD && !ED) {
|
||||
TC.diagnose(D->getStartLoc(), diag::transparent_not_valid);
|
||||
D->getMutableAttrs().Transparent = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_transparent), diag::transparent_not_valid);
|
||||
D->getMutableAttrs().clearAttribute(AK_transparent);
|
||||
|
||||
// Only Struct and Enum extensions can be transparent.
|
||||
} else if (ED) {
|
||||
CanType ExtendedTy = getExtendedType(ED);
|
||||
if (!isa<StructType>(ExtendedTy) && !isa<EnumType>(ExtendedTy)) {
|
||||
TC.diagnose(D->getStartLoc(), diag::transparent_on_invalid_extension);
|
||||
D->getMutableAttrs().Transparent = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_transparent),
|
||||
diag::transparent_on_invalid_extension);
|
||||
D->getMutableAttrs().clearAttribute(AK_transparent);
|
||||
}
|
||||
} else if (AFD->getGenericParams()) {
|
||||
// FIXME: We don't yet support transparent on generic functions.
|
||||
TC.diagnose(D->getStartLoc(), diag::transparent_generic_not_supported);
|
||||
D->getMutableAttrs().Transparent = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_transparent),
|
||||
diag::transparent_generic_not_supported);
|
||||
D->getMutableAttrs().clearAttribute(AK_transparent);
|
||||
|
||||
// Protocol method declarations cannot be transparent.
|
||||
} else if (isa<ProtocolDecl>(AFD->getParent())) {
|
||||
TC.diagnose(D->getStartLoc(),
|
||||
TC.diagnose(Attrs.getLoc(AK_transparent),
|
||||
diag::transparent_in_protocols_not_supported);
|
||||
D->getMutableAttrs().Transparent = false;
|
||||
D->getMutableAttrs().clearAttribute(AK_transparent);
|
||||
|
||||
// Class methods cannot be transparent.
|
||||
} else if (isa<ClassDecl>(AFD->getParent())) {
|
||||
TC.diagnose(D->getStartLoc(),
|
||||
TC.diagnose(Attrs.getLoc(AK_transparent),
|
||||
diag::transparent_in_classes_not_supported);
|
||||
D->getMutableAttrs().Transparent = false;
|
||||
D->getMutableAttrs().clearAttribute(AK_transparent);
|
||||
}
|
||||
}
|
||||
|
||||
if (Attrs.isInOut()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_decl_attribute, "inout");
|
||||
D->getMutableAttrs().InOut = false;
|
||||
}
|
||||
static const AttrKind InvalidAttrs[] = {
|
||||
AK_inout, AK_auto_closure,
|
||||
AK_exported, AK_objc_block, AK_cc, AK_thin, AK_noreturn, AK_local_storage
|
||||
};
|
||||
|
||||
if (Attrs.isAutoClosure()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_decl_attribute, "auto_closure");
|
||||
D->getMutableAttrs().AutoClosure = false;
|
||||
for (AttrKind K : InvalidAttrs) {
|
||||
if (Attrs.has(K)) {
|
||||
TC.diagnose(Attrs.getLoc(K), diag::invalid_decl_attribute);
|
||||
D->getMutableAttrs().clearAttribute(K);
|
||||
}
|
||||
|
||||
if (Attrs.isExported()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_decl_attribute, "exported");
|
||||
D->getMutableAttrs().Exported = false;
|
||||
}
|
||||
|
||||
if (Attrs.isObjCBlock()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_decl_attribute, "objc_block");
|
||||
D->getMutableAttrs().ObjCBlock = false;
|
||||
}
|
||||
|
||||
// Only protocols can have the [class_protocol] attribute.
|
||||
if (Attrs.isClassProtocol() && !isa<ProtocolDecl>(D)) {
|
||||
TC.diagnose(D->getStartLoc(), diag::class_protocol_not_protocol);
|
||||
D->getMutableAttrs().ClassProtocol = false;
|
||||
TC.diagnose(Attrs.getLoc(AK_class_protocol),
|
||||
diag::class_protocol_not_protocol);
|
||||
D->getMutableAttrs().clearAttribute(AK_class_protocol);
|
||||
}
|
||||
|
||||
if (Attrs.hasCC()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_decl_attribute, "cc");
|
||||
D->getMutableAttrs().cc = {};
|
||||
}
|
||||
|
||||
if (Attrs.isThin()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_decl_attribute, "thin");
|
||||
D->getMutableAttrs().Thin = false;
|
||||
}
|
||||
|
||||
if (Attrs.isNoReturn()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_decl_attribute, "noreturn");
|
||||
D->getMutableAttrs().NoReturn = false;
|
||||
}
|
||||
|
||||
if (Attrs.isLocalStorage()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::invalid_decl_attribute, "local_storage");
|
||||
D->getMutableAttrs().LocalStorage = false;
|
||||
}
|
||||
|
||||
if (!isa<FuncDecl>(D)) {
|
||||
if (Attrs.isKernel()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::attribute_requires_function_decl,
|
||||
"kernel");
|
||||
D->getMutableAttrs().KernelOrShader = KernelOrShaderKind::Default;
|
||||
D->getMutableAttrs().clearAttribute(AK_kernel);
|
||||
}
|
||||
if (Attrs.isVertex()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::attribute_requires_function_decl,
|
||||
"vertex");
|
||||
D->getMutableAttrs().KernelOrShader = KernelOrShaderKind::Default;
|
||||
D->getMutableAttrs().clearAttribute(AK_vertex);
|
||||
}
|
||||
if (Attrs.isFragment()) {
|
||||
TC.diagnose(D->getStartLoc(), diag::attribute_requires_function_decl,
|
||||
"fragment");
|
||||
D->getMutableAttrs().KernelOrShader = KernelOrShaderKind::Default;
|
||||
D->getMutableAttrs().clearAttribute(AK_fragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -613,16 +613,16 @@ Type TypeChecker::resolveType(TypeRepr *TyR, DeclContext *DC,
|
||||
if (auto protoTy = Ty->getAs<ProtocolType>()) {
|
||||
Ty = protoTy->getDecl()->getSelf()->getArchetype();
|
||||
} else {
|
||||
diagnose(attrs.AtLoc, diag::sil_self_non_protocol, Ty)
|
||||
diagnose(attrs.getLoc(AK_sil_self), diag::sil_self_non_protocol, Ty)
|
||||
.highlight(AttrTyR->getTypeRepr()->getSourceRange());
|
||||
}
|
||||
attrs.SILSelf = false;
|
||||
attrs.clearAttribute(AK_sil_self);
|
||||
}
|
||||
|
||||
if (attrs.isInOut()) {
|
||||
LValueType::Qual quals;
|
||||
Ty = LValueType::get(Ty, quals, Context);
|
||||
attrs.InOut = false; // so that the empty() check below works
|
||||
attrs.clearAttribute(AK_inout);
|
||||
}
|
||||
|
||||
// Handle the auto_closure, cc, and objc_block attributes for function types.
|
||||
@@ -677,12 +677,15 @@ Type TypeChecker::resolveType(TypeRepr *TyR, DeclContext *DC,
|
||||
Info,
|
||||
Context);
|
||||
}
|
||||
attrs.AutoClosure = false;
|
||||
attrs.ObjCBlock = false;
|
||||
attrs.Thin = false;
|
||||
attrs.NoReturn = false;
|
||||
attrs.clearAttribute(AK_auto_closure);
|
||||
attrs.clearAttribute(AK_objc_block);
|
||||
attrs.clearAttribute(AK_thin);
|
||||
attrs.clearAttribute(AK_noreturn);
|
||||
attrs.clearAttribute(AK_cc);
|
||||
attrs.cc = Nothing;
|
||||
attrs.KernelOrShader = KernelOrShaderKind::Default;
|
||||
attrs.clearAttribute(AK_kernel);
|
||||
attrs.clearAttribute(AK_fragment);
|
||||
attrs.clearAttribute(AK_vertex);
|
||||
}
|
||||
|
||||
// In SIL translation units *only*, permit [weak] and [unowned] to
|
||||
@@ -699,8 +702,8 @@ Type TypeChecker::resolveType(TypeRepr *TyR, DeclContext *DC,
|
||||
if (attrs.isLocalStorage()) {
|
||||
assert(cast<TranslationUnit>(DC->getParentModule())
|
||||
->MainSourceFile->Kind == SourceFile::SIL);
|
||||
diagnose(attrs.AtLoc, diag::sil_local_storage_nested);
|
||||
attrs.LocalStorage = false;
|
||||
diagnose(attrs.getLoc(AK_local_storage),diag::sil_local_storage_nested);
|
||||
attrs.clearAttribute(AK_local_storage);
|
||||
}
|
||||
|
||||
// FIXME: this is lame.
|
||||
|
||||
@@ -1066,7 +1066,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
var->setImplicit();
|
||||
var->setIsObjC(isObjC);
|
||||
if (isIBOutlet)
|
||||
var->getMutableAttrs().IBOutlet = true;
|
||||
var->getMutableAttrs().setAttr(AK_iboutlet, SourceLoc());
|
||||
|
||||
var->setOverriddenDecl(cast_or_null<VarDecl>(getDecl(overriddenID)));
|
||||
break;
|
||||
@@ -1149,24 +1149,24 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
fn->getMutableAttrs().AsmName = ctx.AllocateCopy(blobData);
|
||||
if (isAssignmentOrConversion) {
|
||||
if (fn->isOperator())
|
||||
fn->getMutableAttrs().Assignment = true;
|
||||
fn->getMutableAttrs().setAttr(AK_assignment, SourceLoc());
|
||||
else
|
||||
fn->getMutableAttrs().Conversion = true;
|
||||
fn->getMutableAttrs().setAttr(AK_conversion, SourceLoc());
|
||||
}
|
||||
fn->setIsObjC(isObjC);
|
||||
if (isIBAction)
|
||||
fn->getMutableAttrs().IBAction = true;
|
||||
fn->getMutableAttrs().setAttr(AK_ibaction, SourceLoc());
|
||||
if (isTransparent)
|
||||
fn->getMutableAttrs().Transparent = true;
|
||||
fn->getMutableAttrs().setAttr(AK_transparent, SourceLoc());
|
||||
|
||||
if (Decl *associated = getDecl(associatedDeclID)) {
|
||||
if (auto op = dyn_cast<OperatorDecl>(associated)) {
|
||||
fn->setOperatorDecl(op);
|
||||
|
||||
if (isa<PrefixOperatorDecl>(op))
|
||||
fn->getMutableAttrs().ExplicitPrefix = true;
|
||||
fn->getMutableAttrs().setAttr(AK_prefix, SourceLoc());
|
||||
else if (isa<PostfixOperatorDecl>(op))
|
||||
fn->getMutableAttrs().ExplicitPostfix = true;
|
||||
fn->getMutableAttrs().setAttr(AK_postfix, SourceLoc());
|
||||
// Note that an explicit [infix] is not required.
|
||||
}
|
||||
// Otherwise, unknown associated decl kind.
|
||||
@@ -1238,7 +1238,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
if (isImplicit)
|
||||
proto->setImplicit();
|
||||
if (isClassProtocol)
|
||||
proto->getMutableAttrs().ClassProtocol = true;
|
||||
proto->getMutableAttrs().setAttr(AK_class_protocol, SourceLoc());
|
||||
proto->setIsObjC(isObjC);
|
||||
proto->computeType();
|
||||
|
||||
|
||||
@@ -1149,7 +1149,7 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
auto theClass = cast<ClassDecl>(D);
|
||||
|
||||
DeclAttributes remainingAttrs = theClass->getAttrs();
|
||||
remainingAttrs.ObjC = false;
|
||||
remainingAttrs.clearAttribute(AK_objc);
|
||||
assert(remainingAttrs.empty() && "unhandled class attrs");
|
||||
|
||||
const Decl *DC = getDeclForContext(theClass->getDeclContext());
|
||||
@@ -1175,8 +1175,8 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
auto proto = cast<ProtocolDecl>(D);
|
||||
|
||||
DeclAttributes remainingAttrs = proto->getAttrs();
|
||||
remainingAttrs.ClassProtocol = false;
|
||||
remainingAttrs.ObjC = false;
|
||||
remainingAttrs.clearAttribute(AK_class_protocol);
|
||||
remainingAttrs.clearAttribute(AK_objc);
|
||||
|
||||
assert(remainingAttrs.empty() && "unhandled protocol attrs");
|
||||
|
||||
@@ -1206,8 +1206,8 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
|
||||
DeclAttributes remainingAttrs = var->getAttrs();
|
||||
// FIXME: We need some representation of these for source fidelity.
|
||||
remainingAttrs.ObjC = false;
|
||||
remainingAttrs.IBOutlet = false;
|
||||
remainingAttrs.clearAttribute(AK_objc);
|
||||
remainingAttrs.clearAttribute(AK_iboutlet);
|
||||
|
||||
assert(remainingAttrs.empty() && "unhandled var attrs");
|
||||
|
||||
@@ -1233,17 +1233,18 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
|
||||
DeclAttributes remainingAttrs = fn->getAttrs();
|
||||
// FIXME: We need some representation of these for source fidelity.
|
||||
remainingAttrs.ExplicitPrefix = false;
|
||||
remainingAttrs.ExplicitPostfix = false;
|
||||
remainingAttrs.ExplicitInfix = false;
|
||||
remainingAttrs.Assignment = false;
|
||||
remainingAttrs.Conversion = false;
|
||||
remainingAttrs.clearAttribute(AK_prefix);
|
||||
remainingAttrs.clearAttribute(AK_postfix);
|
||||
remainingAttrs.clearAttribute(AK_infix);
|
||||
remainingAttrs.clearAttribute(AK_assignment);
|
||||
remainingAttrs.clearAttribute(AK_conversion);
|
||||
remainingAttrs.AsmName = {};
|
||||
remainingAttrs.NoReturn = false;
|
||||
remainingAttrs.Thin = false;
|
||||
remainingAttrs.ObjC = false;
|
||||
remainingAttrs.IBAction = false;
|
||||
remainingAttrs.Transparent = false;
|
||||
remainingAttrs.clearAttribute(AK_asmname);
|
||||
remainingAttrs.clearAttribute(AK_noreturn);
|
||||
remainingAttrs.clearAttribute(AK_thin);
|
||||
remainingAttrs.clearAttribute(AK_objc);
|
||||
remainingAttrs.clearAttribute(AK_ibaction);
|
||||
remainingAttrs.clearAttribute(AK_transparent);
|
||||
|
||||
assert(remainingAttrs.empty() && "unhandled func attrs");
|
||||
|
||||
@@ -1306,7 +1307,7 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
auto subscript = cast<SubscriptDecl>(D);
|
||||
|
||||
DeclAttributes remainingAttrs = subscript->getAttrs();
|
||||
remainingAttrs.ObjC = false;
|
||||
remainingAttrs.clearAttribute(AK_objc);
|
||||
assert(remainingAttrs.empty() && "unhandled subscript attrs");
|
||||
|
||||
const Decl *DC = getDeclForContext(subscript->getDeclContext());
|
||||
@@ -1331,8 +1332,8 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
auto ctor = cast<ConstructorDecl>(D);
|
||||
|
||||
DeclAttributes remainingAttrs = ctor->getAttrs();
|
||||
remainingAttrs.ObjC = false;
|
||||
remainingAttrs.Transparent = false;
|
||||
remainingAttrs.clearAttribute(AK_objc);
|
||||
remainingAttrs.clearAttribute(AK_transparent);
|
||||
|
||||
assert(remainingAttrs.empty() && "unhandled constructor attrs");
|
||||
|
||||
@@ -1359,7 +1360,7 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
auto dtor = cast<DestructorDecl>(D);
|
||||
|
||||
DeclAttributes remainingAttrs = dtor->getAttrs();
|
||||
remainingAttrs.ObjC = false;
|
||||
remainingAttrs.clearAttribute(AK_objc);
|
||||
assert(remainingAttrs.empty() && "unhandled destructor attrs");
|
||||
|
||||
const Decl *DC = getDeclForContext(dtor->getDeclContext());
|
||||
|
||||
Reference in New Issue
Block a user