зеркало из https://github.com/microsoft/clang-1.git
This patch implementa objective-c's @compatibilty-alias declaration.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42883 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
8a12c2777c
Коммит
243b64b000
|
@ -35,6 +35,7 @@ static unsigned nCategoryDecls = 0;
|
|||
static unsigned nIvarDecls = 0;
|
||||
static unsigned nObjcImplementationDecls = 0;
|
||||
static unsigned nObjcCategoryImpl = 0;
|
||||
static unsigned nObjcCompatibleAlias = 0;
|
||||
|
||||
static bool StatSwitch = false;
|
||||
|
||||
|
@ -141,6 +142,10 @@ void Decl::PrintStats() {
|
|||
nObjcCategoryImpl, (int)sizeof(ObjcCategoryImplDecl),
|
||||
int(nObjcCategoryImpl*sizeof(ObjcCategoryImplDecl)));
|
||||
|
||||
fprintf(stderr, " %d compatibility alias decls, %d each (%d bytes)\n",
|
||||
nObjcCompatibleAlias, (int)sizeof(ObjcCompatibleAliasDecl),
|
||||
int(nObjcCompatibleAlias*sizeof(ObjcCompatibleAliasDecl)));
|
||||
|
||||
fprintf(stderr, "Total bytes = %d\n",
|
||||
int(nFuncs*sizeof(FunctionDecl)+nBlockVars*sizeof(BlockVarDecl)+
|
||||
nFileVars*sizeof(FileVarDecl)+nParmVars*sizeof(ParmVarDecl)+
|
||||
|
@ -207,6 +212,9 @@ void Decl::addDeclKind(const Kind k) {
|
|||
case ObjcCategoryImpl:
|
||||
nObjcCategoryImpl++;
|
||||
break;
|
||||
case CompatibleAlias:
|
||||
nObjcCompatibleAlias++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,12 @@ static void PrintObjcCategoryDecl(ObjcCategoryDecl *PID) {
|
|||
// FIXME: implement the rest...
|
||||
}
|
||||
|
||||
static void PrintObjcCompatibleAliasDecl(ObjcCompatibleAliasDecl *AID) {
|
||||
std::string A = AID->getName();
|
||||
std::string I = AID->getClassInterface()->getName();
|
||||
fprintf(stderr, "@compatibility_alias %s %s;\n", A.c_str(), I.c_str());
|
||||
}
|
||||
|
||||
namespace {
|
||||
class ASTPrinter : public ASTConsumer {
|
||||
virtual void HandleTopLevelDecl(Decl *D) {
|
||||
|
@ -153,6 +159,9 @@ namespace {
|
|||
} else if (ObjcCategoryDecl *OID =
|
||||
dyn_cast<ObjcCategoryDecl>(D)) {
|
||||
PrintObjcCategoryDecl(OID);
|
||||
} else if (ObjcCompatibleAliasDecl *OID =
|
||||
dyn_cast<ObjcCompatibleAliasDecl>(D)) {
|
||||
PrintObjcCompatibleAliasDecl(OID);
|
||||
} else if (isa<ObjcClassDecl>(D)) {
|
||||
fprintf(stderr, "@class [printing todo]\n");
|
||||
} else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
|
||||
|
|
|
@ -923,15 +923,22 @@ Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
|
|||
Diag(Tok, diag::err_expected_ident);
|
||||
return 0;
|
||||
}
|
||||
ConsumeToken(); // consume alias-name
|
||||
IdentifierInfo *aliasId = Tok.getIdentifierInfo();
|
||||
SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
Diag(Tok, diag::err_expected_ident);
|
||||
return 0;
|
||||
}
|
||||
ConsumeToken(); // consume class-name;
|
||||
if (Tok.isNot(tok::semi))
|
||||
IdentifierInfo *classId = Tok.getIdentifierInfo();
|
||||
SourceLocation classLoc = ConsumeToken(); // consume class-name;
|
||||
if (Tok.isNot(tok::semi)) {
|
||||
Diag(Tok, diag::err_expected_semi_after, "@compatibility_alias");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
DeclTy *ClsType = Actions.ActOnCompatiblityAlias(atLoc,
|
||||
aliasId, aliasLoc,
|
||||
classId, classLoc);
|
||||
return ClsType;
|
||||
}
|
||||
|
||||
/// property-synthesis:
|
||||
|
|
|
@ -416,6 +416,11 @@ public:
|
|||
IdentifierInfo *SuperName, SourceLocation SuperLoc,
|
||||
IdentifierInfo **ProtocolNames, unsigned NumProtocols,
|
||||
AttributeList *AttrList);
|
||||
|
||||
virtual DeclTy *ActOnCompatiblityAlias(
|
||||
SourceLocation AtCompatibilityAliasLoc,
|
||||
IdentifierInfo *AliasName, SourceLocation AliasLocation,
|
||||
IdentifierInfo *ClassName, SourceLocation ClassLocation);
|
||||
|
||||
virtual DeclTy *ActOnStartProtocolInterface(
|
||||
SourceLocation AtProtoInterfaceLoc,
|
||||
|
|
|
@ -31,6 +31,9 @@ Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
|
|||
if (Decl *IIDecl = II.getFETokenInfo<Decl>())
|
||||
if (isa<TypedefDecl>(IIDecl) || isa<ObjcInterfaceDecl>(IIDecl))
|
||||
return IIDecl;
|
||||
else if (ObjcCompatibleAliasDecl *ADecl =
|
||||
dyn_cast<ObjcCompatibleAliasDecl>(IIDecl))
|
||||
return ADecl->getClassInterface();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -961,6 +964,49 @@ Sema::DeclTy *Sema::ActOnStartClassInterface(
|
|||
return IDecl;
|
||||
}
|
||||
|
||||
/// ActOnCompatiblityAlias - this action is called after complete parsing of
|
||||
/// @compaatibility_alias declaration. It sets up the alias relationships.
|
||||
Sema::DeclTy *Sema::ActOnCompatiblityAlias(
|
||||
SourceLocation AtCompatibilityAliasLoc,
|
||||
IdentifierInfo *AliasName, SourceLocation AliasLocation,
|
||||
IdentifierInfo *ClassName, SourceLocation ClassLocation) {
|
||||
// Look for previous declaration of alias name
|
||||
ScopedDecl *ADecl = LookupScopedDecl(AliasName, Decl::IDNS_Ordinary,
|
||||
AliasLocation, TUScope);
|
||||
if (ADecl) {
|
||||
if (isa<ObjcCompatibleAliasDecl>(ADecl)) {
|
||||
Diag(AliasLocation, diag::warn_previous_alias_decl);
|
||||
Diag(ADecl->getLocation(), diag::warn_previous_declaration);
|
||||
}
|
||||
else {
|
||||
Diag(AliasLocation, diag::err_conflicting_aliasing_type,
|
||||
AliasName->getName());
|
||||
Diag(ADecl->getLocation(), diag::err_previous_declaration);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// Check for class declaration
|
||||
ScopedDecl *CDecl = LookupScopedDecl(ClassName, Decl::IDNS_Ordinary,
|
||||
ClassLocation, TUScope);
|
||||
if (!CDecl || !isa<ObjcInterfaceDecl>(CDecl)) {
|
||||
Diag(ClassLocation, diag::warn_undef_interface,
|
||||
ClassName->getName());
|
||||
if (CDecl)
|
||||
Diag(CDecl->getLocation(), diag::warn_previous_declaration);
|
||||
return 0;
|
||||
}
|
||||
// Everything checked out, instantiate a new alias declaration ast
|
||||
ObjcCompatibleAliasDecl *AliasDecl =
|
||||
new ObjcCompatibleAliasDecl(AtCompatibilityAliasLoc,
|
||||
AliasName,
|
||||
dyn_cast<ObjcInterfaceDecl>(CDecl));
|
||||
|
||||
// Chain & install the interface decl into the identifier.
|
||||
AliasDecl->setNext(AliasName->getFETokenInfo<ScopedDecl>());
|
||||
AliasName->setFETokenInfo(AliasDecl);
|
||||
return AliasDecl;
|
||||
}
|
||||
|
||||
Sema::DeclTy *Sema::ActOnStartProtocolInterface(
|
||||
SourceLocation AtProtoInterfaceLoc,
|
||||
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
ObjcImplementation,
|
||||
ObjcProtocol,
|
||||
// ScopedDecl
|
||||
CompatibleAlias,
|
||||
// TypeDecl
|
||||
ObjcInterface,
|
||||
Typedef,
|
||||
|
@ -68,7 +69,7 @@ public:
|
|||
// of the class, to allow efficient classof.
|
||||
NamedFirst = Field, NamedLast = ParmVar,
|
||||
FieldFirst = Field, FieldLast = ObjcIvar,
|
||||
ScopedFirst = ObjcInterface, ScopedLast = ParmVar,
|
||||
ScopedFirst = CompatibleAlias, ScopedLast = ParmVar,
|
||||
TypeFirst = ObjcInterface, TypeLast = Class,
|
||||
TagFirst = Enum , TagLast = Class,
|
||||
RecordFirst = Struct , RecordLast = Class,
|
||||
|
@ -124,6 +125,7 @@ public:
|
|||
case ParmVar:
|
||||
case EnumConstant:
|
||||
case ObjcInterface:
|
||||
case CompatibleAlias:
|
||||
return IDNS_Ordinary;
|
||||
case Struct:
|
||||
case Union:
|
||||
|
|
|
@ -591,7 +591,27 @@ public:
|
|||
}
|
||||
static bool classof(const ObjcImplementationDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// ObjcCompatibleAliasDecl - Represents alias of a class. This alias is
|
||||
/// declared as @compatibility_alias alias class.
|
||||
class ObjcCompatibleAliasDecl : public ScopedDecl {
|
||||
/// Class that this is an alias of.
|
||||
ObjcInterfaceDecl *AliasedClass;
|
||||
|
||||
public:
|
||||
ObjcCompatibleAliasDecl(SourceLocation L, IdentifierInfo *Id,
|
||||
ObjcInterfaceDecl* aliasedClass)
|
||||
: ScopedDecl(CompatibleAlias, L, Id, 0),
|
||||
AliasedClass(aliasedClass) {}
|
||||
|
||||
ObjcInterfaceDecl *getClassInterface() const { return AliasedClass; }
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == CompatibleAlias;
|
||||
}
|
||||
static bool classof(const ObjcCompatibleAliasDecl *D) { return true; }
|
||||
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
#endif
|
||||
|
|
|
@ -446,7 +446,12 @@ DIAG(err_undeclared_protocol, ERROR,
|
|||
"cannot find protocol declaration for '%0'")
|
||||
DIAG(err_missing_id_definition, ERROR,
|
||||
"cannot find definition of 'id'")
|
||||
|
||||
DIAG(warn_previous_alias_decl, WARNING,
|
||||
"previously declared alias is ignored")
|
||||
DIAG(warn_previous_declaration, WARNING,
|
||||
"previous declaration is here")
|
||||
DIAG(err_conflicting_aliasing_type, ERROR,
|
||||
"conflicting types for alias %0'")
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Semantic Analysis
|
||||
|
|
|
@ -455,6 +455,16 @@ public:
|
|||
AttributeList *AttrList) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ActOnCompatiblityAlias - this action is called after complete parsing of
|
||||
/// @compaatibility_alias declaration. It sets up the alias relationships.
|
||||
virtual DeclTy *ActOnCompatiblityAlias(
|
||||
SourceLocation AtCompatibilityAliasLoc,
|
||||
IdentifierInfo *AliasName, SourceLocation AliasLocation,
|
||||
IdentifierInfo *ClassName, SourceLocation ClassLocation) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ActOnStartProtocolInterface - this action is called immdiately after
|
||||
// parsing the prologue for a protocol interface.
|
||||
virtual DeclTy *ActOnStartProtocolInterface(
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// RUN: clang -ast-print %s
|
||||
|
||||
@protocol P1 @end
|
||||
@protocol P2 @end
|
||||
|
||||
@interface INTF @end
|
||||
|
||||
@compatibility_alias alias INTF;
|
||||
|
||||
|
||||
int foo ()
|
||||
{
|
||||
INTF *pi;
|
||||
INTF<P2,P1> *pi2;
|
||||
alias *p;
|
||||
alias<P1,P2> *p2;
|
||||
return pi2 == p2;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
|
||||
@compatibility_alias alias4 foo; // expected-warning {{cannot find interface declaration for 'foo'}}
|
||||
|
||||
@class class2;
|
||||
@class class3;
|
||||
|
||||
typedef int I; // expected-warning {{previous declaration is here}}
|
||||
|
||||
@compatibility_alias alias1 I; // expected-warning {{cannot find interface declaration for 'I'}}
|
||||
|
||||
@compatibility_alias alias class2; // expected-warning {{previous declaration is here}}
|
||||
@compatibility_alias alias class3; // expected-warning {{previously declared alias is ignored}}
|
||||
|
||||
|
||||
typedef int alias2; // expected-error {{previous declaration is here}}
|
||||
@compatibility_alias alias2 class3; // expected-error {{conflicting types for alias alias2'}}
|
||||
|
||||
alias *p;
|
||||
class2 *p2;
|
||||
|
||||
int foo ()
|
||||
{
|
||||
|
||||
if (p == p2) {
|
||||
int alias = 1;
|
||||
}
|
||||
|
||||
alias *p3;
|
||||
return p3 == p2;
|
||||
}
|
Загрузка…
Ссылка в новой задаче