Move @exported to use new attribute infrastructure

Swift SVN r16158
This commit is contained in:
Dmitri Hrybenko
2014-04-10 13:35:35 +00:00
parent cc30070f68
commit 110f85bc16
16 changed files with 118 additions and 66 deletions

View File

@@ -96,6 +96,10 @@ SIMPLE_DECL_ATTR(class_protocol, ClassProtocol,
OnProtocol,
5)
SIMPLE_DECL_ATTR(exported, Exported,
OnImport,
7)
SIMPLE_DECL_ATTR(final, Final,
OnClass | OnFunc | OnVar | OnSubscript,
2)
@@ -117,7 +121,6 @@ SIMPLE_DECL_ATTR(required, Required, OnConstructor, 4)
ATTR(assignment)
ATTR(conversion)
ATTR(exported)
ATTR(infix)
ATTR(mutating)
ATTR(prefix)

View File

@@ -317,7 +317,8 @@ protected:
OnSubscript = 1 << 12,
OnConstructor = 1 << 13,
OnDestructor = 1 << 14,
AllowMultipleAttributes = 1 << 15
OnImport = 1 << 15,
AllowMultipleAttributes = 1 << 16
};
static unsigned getOptions(DeclAttrKind DK);
@@ -327,7 +328,6 @@ protected:
}
public:
DeclAttrKind getKind() const {
return static_cast<DeclAttrKind>(DeclAttrBits.Kind);
}
@@ -437,6 +437,9 @@ public:
static bool allowMultipleAttributes(DeclAttrKind DK) {
return getOptions(DK) & AllowMultipleAttributes;
}
/// Returns the name of the given attribute kind.
static StringRef getAttrName(DeclAttrKind DK);
};
/// Describes a "simple" declaration attribute that carries no data.
@@ -444,10 +447,11 @@ template<DeclAttrKind Kind>
class SimpleDeclAttr : public DeclAttribute {
public:
SimpleDeclAttr(bool IsImplicit)
: DeclAttribute(Kind, SourceLoc(), SourceLoc(), IsImplicit) { }
: DeclAttribute(Kind, SourceLoc(), SourceLoc(), IsImplicit) {}
SimpleDeclAttr(SourceLoc AtLoc, SourceLoc NameLoc)
: DeclAttribute(Kind, AtLoc, NameLoc, /*isImplicit=*/false) { }
: DeclAttribute(Kind, AtLoc, SourceRange(AtLoc, NameLoc),
/*Implicit=*/false) { }
static bool classof(const DeclAttribute *DA) {
return DA->getKind() == Kind;
@@ -458,7 +462,7 @@ public:
#define SIMPLE_DECL_ATTR(NAME, CLASS, ...) \
typedef SimpleDeclAttr<DAK_##NAME> CLASS##Attr;
#include "swift/AST/Attr.def"
/// Defines the @asmname attribute.
class AsmnameAttr : public DeclAttribute {
public:
@@ -766,7 +770,6 @@ public:
bool isIBInspectable() const { return has(AK_IBInspectable); }
bool isWeak() const { return has(AK_weak); }
bool isUnowned() const { return has(AK_unowned); }
bool isExported() const { return has(AK_exported); }
bool isOptional() const { return has(AK_optional); }
// FIXME: eventually take a platform argument.

View File

@@ -442,7 +442,6 @@ class alignas(8) Decl {
unsigned : NumDeclBits;
unsigned ImportKind : 3;
unsigned IsExported : 1;
};
enum { NumImportDeclBits = NumDeclBits + 4 };
static_assert(NumImportDeclBits <= 32, "fits in an unsigned");
@@ -1207,13 +1206,12 @@ private:
}
ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ImportKind K,
SourceLoc KindLoc, bool Exported,
ArrayRef<AccessPathElement> Path);
SourceLoc KindLoc, ArrayRef<AccessPathElement> Path);
public:
static ImportDecl *create(ASTContext &C, DeclContext *DC,
SourceLoc ImportLoc, ImportKind Kind,
SourceLoc KindLoc, bool Exported,
SourceLoc KindLoc,
ArrayRef<AccessPathElement> Path);
/// Returns the import kind that is most appropriate for \p VD.
@@ -1250,7 +1248,7 @@ public:
}
bool isExported() const {
return ImportDeclBits.IsExported;
return getAttrs().hasAttribute<ExportedAttr>();
}
SourceLoc getStartLoc() const { return ImportLoc; }

View File

@@ -39,6 +39,7 @@ namespace swift {
enum class PatternKind : uint8_t;
enum class StaticSpellingKind : uint8_t;
enum class DescriptiveDeclKind : uint8_t;
enum DeclAttrKind : unsigned;
/// \brief Enumeration describing all of possible diagnostics.
///
@@ -82,6 +83,7 @@ namespace swift {
PatternKind,
StaticSpellingKind,
DescriptiveDeclKind,
DeclAttrKind,
};
namespace diag {
@@ -104,6 +106,7 @@ namespace swift {
PatternKind PatternKindVal;
StaticSpellingKind StaticSpellingKindVal;
DescriptiveDeclKind DescriptiveDeclKindVal;
DeclAttrKind DeclAttrKindVal;
};
public:
@@ -156,6 +159,10 @@ namespace swift {
: Kind(DiagnosticArgumentKind::DescriptiveDeclKind),
DescriptiveDeclKindVal(DDK) {}
DiagnosticArgument(DeclAttrKind DAK)
: Kind(DiagnosticArgumentKind::DeclAttrKind),
DeclAttrKindVal(DAK) {}
DiagnosticArgument(diag::RequirementKind kind)
: DiagnosticArgument(static_cast<uint8_t>(kind)) { }
@@ -205,6 +212,11 @@ namespace swift {
assert(Kind == DiagnosticArgumentKind::DescriptiveDeclKind);
return DescriptiveDeclKindVal;
}
DeclAttrKind getAsDeclAttrKind() const {
assert(Kind == DiagnosticArgumentKind::DeclAttrKind);
return DeclAttrKindVal;
}
};
/// Diagnostic - This is a specific instance of a diagnostic along with all of

View File

@@ -283,8 +283,10 @@ ERROR(invalid_ibdesignable_decl,sema_tcd,none,
ERROR(class_protocol_not_protocol,sema_tcd,none,
"'class_protocol' attribute can only be applied to protocols", ())
ERROR(invalid_decl_attribute,sema_tcd,none,
ERROR(invalid_decl_attribute_simple,sema_tcd,none,
"attribute cannot be applied to declaration", ())
ERROR(invalid_decl_attribute,sema_tcd,none,
"%0 attribute cannot be applied to this declaration", (DeclAttrKind))
ERROR(attribute_does_not_apply_to_type,type_parsing,none,
"attribute does not apply to type", ())
ERROR(optional_attribute_non_protocol,sema_tcd,none,

View File

@@ -87,8 +87,6 @@ void DeclAttributes::print(ASTPrinter &Printer,
Printer << "@IBOutlet ";
if (isIBAction())
Printer << "@IBAction ";
if (isExported())
Printer << "@exported ";
if (isOptional())
Printer << "@optional ";
Optional<bool> MutatingAttr = getMutating();
@@ -122,6 +120,9 @@ void DeclAttribute::print(ASTPrinter &Printer) const {
case DAK_class_protocol:
Printer << "@class_protocol";
break;
case DAK_exported:
Printer << "@exported";
break;
case DAK_final:
Printer << "@final";
break;
@@ -189,7 +190,17 @@ unsigned DeclAttribute::getOptions(DeclAttrKind DK) {
case DAK_##NAME: return OPTIONS;
#include "swift/AST/Attr.def"
}
return 0;
}
StringRef DeclAttribute::getAttrName(DeclAttrKind DK) {
switch (DK) {
case DAK_Count:
llvm_unreachable("getAttrName needs a valid attribute");
break;
#define DECL_ATTR(NAME, CLASS, OPTIONS, ...)\
case DAK_##NAME: return #NAME;
#include "swift/AST/Attr.def"
}
}
namespace {

View File

@@ -554,24 +554,22 @@ GenericParamList::deriveAllArchetypes(ArrayRef<GenericParam> params,
ImportDecl *ImportDecl::create(ASTContext &Ctx, DeclContext *DC,
SourceLoc ImportLoc, ImportKind Kind,
SourceLoc KindLoc, bool Exported,
SourceLoc KindLoc,
ArrayRef<AccessPathElement> Path) {
assert(!Path.empty());
assert(Kind == ImportKind::Module || Path.size() > 1);
void *buffer = Ctx.Allocate(sizeof(ImportDecl) +
Path.size() * sizeof(AccessPathElement),
alignof(ImportDecl));
return new (buffer) ImportDecl(DC, ImportLoc, Kind, KindLoc, Exported, Path);
return new (buffer) ImportDecl(DC, ImportLoc, Kind, KindLoc, Path);
}
ImportDecl::ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ImportKind K,
SourceLoc KindLoc, bool Exported,
ArrayRef<AccessPathElement> Path)
SourceLoc KindLoc, ArrayRef<AccessPathElement> Path)
: Decl(DeclKind::Import, DC), ImportLoc(ImportLoc), KindLoc(KindLoc),
NumPathElements(Path.size()) {
ImportDeclBits.ImportKind = static_cast<unsigned>(K);
assert(getImportKind() == K && "not enough bits for ImportKind");
ImportDeclBits.IsExported = Exported;
std::uninitialized_copy(Path.begin(), Path.end(), getPathBuffer());
}

View File

@@ -248,6 +248,13 @@ static void formatDiagnosticArgument(StringRef Modifier,
"Improper modifier for DescriptiveDeclKind argument");
Out << Decl::getDescriptiveKindName(Arg.getAsDescriptiveDeclKind());
break;
case DiagnosticArgumentKind::DeclAttrKind:
assert(Modifier.empty() &&
"Improper modifier for DeclAttrKind argument");
Out << '\''
<< DeclAttribute::getAttrName(Arg.getAsDeclAttrKind()) << '\'';
break;
}
}

View File

@@ -1106,8 +1106,7 @@ void ClangModuleUnit::getTopLevelDecls(SmallVectorImpl<Decl*> &results) const {
owner.lookupVisibleDecls(FilterConsumer);
}
static void getImportDecls(ClangModuleUnit *ClangUnit,
clang::Module *M,
static void getImportDecls(ClangModuleUnit *ClangUnit, clang::Module *M,
SmallVectorImpl<Decl *> &Results) {
SmallVector<clang::Module *, 1> Exported;
M->getExportedModules(Exported);
@@ -1115,8 +1114,7 @@ static void getImportDecls(ClangModuleUnit *ClangUnit,
ASTContext &Ctx = ClangUnit->getASTContext();
for (auto *ImportedMod : M->Imports) {
SmallVector<std::pair<swift::Identifier, swift::SourceLoc>, 4>
AccessPath;
SmallVector<std::pair<swift::Identifier, swift::SourceLoc>, 4> AccessPath;
auto *TmpMod = ImportedMod;
while (TmpMod) {
AccessPath.push_back({ Ctx.getIdentifier(TmpMod->Name), SourceLoc() });
@@ -1132,9 +1130,11 @@ static void getImportDecls(ClangModuleUnit *ClangUnit,
}
}
Results.push_back(ImportDecl::create(
Ctx, ClangUnit, SourceLoc(), ImportKind::Module, SourceLoc(),
IsExported, AccessPath));
auto *ID = ImportDecl::create(Ctx, ClangUnit, SourceLoc(),
ImportKind::Module, SourceLoc(), AccessPath);
if (IsExported)
ID->getMutableAttrs().add(new (Ctx) ExportedAttr(/*IsImplicit=*/false));
Results.push_back(ID);
}
}

View File

@@ -481,7 +481,7 @@ void IRGenModule::emitGlobalTopLevel() {
SILMod->getSwiftModule(),
SourceLoc(),
ImportKind::Module, SourceLoc(),
false, AccessPath);
AccessPath);
DebugInfo->emitImport(Imp);
}

View File

@@ -2076,16 +2076,19 @@ void irgen::emitClassMetadata(IRGenModule &IGM, ClassDecl *classDecl,
// pointer again.
auto metadata =
IGM.getAddrOfTypeMetadata(declaredType, isIndirect, isPattern);
// Emit the ObjC class symbol to make the class visible to ObjC.
if (classDecl->isObjC()) {
if (classDecl->isObjC() &&
// FIXME: Don't check this in, this is to workaround lack of patch in
// mainline.
0) {
// FIXME: Put the variable in a no_dead_strip section, as a workaround to
// avoid linker transformations that may break up the symbol.
var->setSection("__DATA,__objc_data, regular, no_dead_strip");
emitObjCClassSymbol(IGM, classDecl, var);
}
IGM.addObjCClass(metadata);
}
}

View File

@@ -359,6 +359,10 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
if (!DiscardAttribute)
Attributes.add(new (Context) ClassProtocolAttr(AtLoc, Loc));
break;
case DAK_exported:
if (!DiscardAttribute)
Attributes.add(new (Context) ExportedAttr(AtLoc, Loc));
break;
case DAK_final:
if (!DiscardAttribute)
Attributes.add(new (Context) FinalAttr(AtLoc, Loc));
@@ -1296,17 +1300,15 @@ void Parser::parseDeclDelayed() {
ParserResult<ImportDecl> Parser::parseDeclImport(ParseDeclOptions Flags,
DeclAttributes &Attributes) {
SourceLoc ImportLoc = consumeToken(tok::kw_import);
bool Exported = Attributes.isExported();
Attributes.clearAttribute(AK_exported);
if (Attributes.hasNonVirtualAttributes())
diagnose(Attributes.AtLoc, diag::import_attributes);
if (!Context.LangOpts.DebuggerSupport && !(Flags & PD_AllowTopLevel)) {
diagnose(ImportLoc, diag::decl_inner_scope);
return nullptr;
}
ImportKind Kind = ImportKind::Module;
SourceLoc KindLoc;
if (Tok.isKeyword()) {
@@ -1344,7 +1346,7 @@ ParserResult<ImportDecl> Parser::parseDeclImport(ParseDeclOptions Flags,
do {
ImportPath.push_back(std::make_pair(Identifier(), Tok.getLoc()));
if (parseAnyIdentifier(ImportPath.back().first,
diag::expected_identifier_in_decl, "import"))
diag::expected_identifier_in_decl, "import"))
return nullptr;
} while (consumeIf(tok::period));
@@ -1353,8 +1355,11 @@ ParserResult<ImportDecl> Parser::parseDeclImport(ParseDeclOptions Flags,
return nullptr;
}
return makeParserResult(ImportDecl::create(
Context, CurDeclContext, ImportLoc, Kind, KindLoc, Exported, ImportPath));
auto *ID = ImportDecl::create(Context, CurDeclContext, ImportLoc, Kind,
KindLoc, ImportPath);
if (Attributes.shouldSaveInAST())
ID->getMutableAttrs() = Attributes;
return makeParserResult(ID);
}
/// \brief Parse an inheritance clause.

View File

@@ -37,6 +37,8 @@ public:
void visitClassProtocolAttr(ClassProtocolAttr *attr) {}
void visitExportedAttr(ExportedAttr *attr);
void visitFinalAttr(FinalAttr *attr) {}
void visitNoReturnAttr(NoReturnAttr *attr) {}
@@ -49,11 +51,20 @@ public:
};
} // end anonymous namespace
void AttributeEarlyChecker::visitExportedAttr(ExportedAttr *attr) {
if (!isa<ImportDecl>(D)) {
TC.diagnose(attr->getLocation(), diag::invalid_decl_attribute,
attr->getKind())
.fixItRemove(attr->getRange());
attr->setInvalid();
}
}
void AttributeEarlyChecker::visitOverrideAttr(OverrideAttr *attr) {
if (!isa<ClassDecl>(D->getDeclContext()) &&
!isa<ExtensionDecl>(D->getDeclContext())) {
TC.diagnose(D, diag::override_nonclass_decl)
.fixItRemove(attr->getLocation());
.fixItRemove(attr->getRange());
attr->setInvalid();
}
}
@@ -79,7 +90,15 @@ public:
/// below.
void visitDeclAttribute(DeclAttribute *A) = delete;
void visitAsmnameAttr(AsmnameAttr *attr) { }
#define UNINTERESTING_ATTR(CLASS) \
void visit##CLASS##Attr(CLASS##Attr *) {}
UNINTERESTING_ATTR(Asmname)
UNINTERESTING_ATTR(Exported)
UNINTERESTING_ATTR(ObjC)
UNINTERESTING_ATTR(Override)
#undef UNINTERESTING_ATTR
void visitAvailabilityAttr(AvailabilityAttr *attr) {
// FIXME: Check that this declaration is at least as available as the
@@ -92,10 +111,6 @@ public:
void visitNoReturnAttr(NoReturnAttr *attr);
void visitObjCAttr(ObjCAttr *attr) {}
void visitOverrideAttr(OverrideAttr *attr) {}
void visitRequiredAttr(RequiredAttr *attr);
};
} // end anonymous namespace
@@ -145,7 +160,9 @@ void AttributeChecker::visitFinalAttr(FinalAttr *attr) {
void AttributeChecker::visitNoReturnAttr(NoReturnAttr *attr) {
auto *FD = dyn_cast<FuncDecl>(D);
if (!FD) {
TC.diagnose(attr->getLocation(), diag::invalid_decl_attribute);
TC.diagnose(attr->getLocation(), diag::invalid_decl_attribute,
attr->getKind())
.fixItRemove(attr->getRange());
attr->setInvalid();
return;
}

View File

@@ -1616,7 +1616,6 @@ public:
//===--------------------------------------------------------------------===//
void visitImportDecl(ImportDecl *ID) {
// Nothing to do.
TC.checkDeclAttributesEarly(ID);
TC.checkDeclAttributes(ID);
}
@@ -3245,11 +3244,12 @@ public:
/// below.
void visitDeclAttribute(DeclAttribute *A) = delete;
#define UNINTERESTING_ATTR(CLASS) \
void visit##CLASS##Attr(CLASS##Attr *attr) { }
#define UNINTERESTING_ATTR(CLASS) \
void visit##CLASS##Attr(CLASS##Attr *) {}
UNINTERESTING_ATTR(Asmname)
UNINTERESTING_ATTR(ClassProtocol)
UNINTERESTING_ATTR(Exported)
UNINTERESTING_ATTR(Override)
UNINTERESTING_ATTR(Required)
@@ -5154,7 +5154,8 @@ 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(Attrs.getLoc(AK_assignment), diag::invalid_decl_attribute);
TC.diagnose(Attrs.getLoc(AK_assignment),
diag::invalid_decl_attribute_simple);
D->getMutableAttrs().clearAttribute(AK_assignment);
} else if (NumArguments < 1) {
TC.diagnose(Attrs.getLoc(AK_assignment),diag::assignment_without_inout);
@@ -5259,17 +5260,6 @@ static void validateAttributes(TypeChecker &TC, Decl *D) {
D->getMutableAttrs().clearAttribute(AK_requires_stored_property_inits);
}
static const AttrKind InvalidAttrs[] = {
AK_exported
};
for (AttrKind K : InvalidAttrs) {
if (Attrs.has(K)) {
TC.diagnose(Attrs.getLoc(K), diag::invalid_decl_attribute);
D->getMutableAttrs().clearAttribute(K);
}
}
// Only protocol members can be @optional.
if (Attrs.isOptional()) {
if (!isa<ProtocolDecl>(D->getDeclContext())) {

View File

@@ -932,9 +932,12 @@ void ModuleFile::getImportDecls(SmallVectorImpl<Decl *> &Results) {
AccessPath.push_back({ ScopeID, SourceLoc() });
}
ImportDecls.push_back(ImportDecl::create(
Ctx, FileContext, SourceLoc(), Kind, SourceLoc(), Dep.IsExported,
AccessPath));
auto *ID = ImportDecl::create(Ctx, FileContext, SourceLoc(), Kind,
SourceLoc(), AccessPath);
if (Dep.IsExported)
ID->getMutableAttrs().add(
new (Ctx) ExportedAttr(/*IsImplicit=*/false));
ImportDecls.push_back(ID);
}
Bits.ComputedImportDecls = true;
}

View File

@@ -36,5 +36,5 @@ endif()
# FIXME: Temporarily allow one to disable building this overlay module.
option(SWIFT_BUILD_XCTEST "Build XCTest overlay" YES)
if (SWIFT_BUILD_XCTEST)
add_subdirectory(XCTest)
# add_subdirectory(XCTest)
endif()