summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2007-10-11 23:42:27 +0000
committerFariborz Jahanian <fjahanian@apple.com>2007-10-11 23:42:27 +0000
commit49c6425ee697c54cc584376b1a7a7556947f8b84 (patch)
treebcca18b1e3510e739c3221719b58462ec99996b7
parent6472eb63c200f4fba8866c6965b21c86cbc4cd21 (diff)
downloadbcm5719-llvm-49c6425ee697c54cc584376b1a7a7556947f8b84.tar.gz
bcm5719-llvm-49c6425ee697c54cc584376b1a7a7556947f8b84.zip
This patch implementa objective-c's @compatibilty-alias declaration.
llvm-svn: 42883
-rw-r--r--clang/AST/Decl.cpp8
-rw-r--r--clang/Driver/ASTConsumers.cpp9
-rw-r--r--clang/Parse/ParseObjc.cpp15
-rw-r--r--clang/Sema/Sema.h5
-rw-r--r--clang/Sema/SemaDecl.cpp46
-rw-r--r--clang/include/clang/AST/Decl.h4
-rw-r--r--clang/include/clang/AST/DeclObjC.h20
-rw-r--r--clang/include/clang/Basic/DiagnosticKinds.def7
-rw-r--r--clang/include/clang/Parse/Action.h10
-rw-r--r--clang/test/Parser/objc-alias-printing.m18
-rw-r--r--clang/test/Sema/alias-test-1.m31
11 files changed, 167 insertions, 6 deletions
diff --git a/clang/AST/Decl.cpp b/clang/AST/Decl.cpp
index 20117795254..987e4933a08 100644
--- a/clang/AST/Decl.cpp
+++ b/clang/AST/Decl.cpp
@@ -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;
}
}
diff --git a/clang/Driver/ASTConsumers.cpp b/clang/Driver/ASTConsumers.cpp
index 1ec2c72d522..114940fa6ba 100644
--- a/clang/Driver/ASTConsumers.cpp
+++ b/clang/Driver/ASTConsumers.cpp
@@ -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)) {
diff --git a/clang/Parse/ParseObjc.cpp b/clang/Parse/ParseObjc.cpp
index dad82eec52b..bfd6797c964 100644
--- a/clang/Parse/ParseObjc.cpp
+++ b/clang/Parse/ParseObjc.cpp
@@ -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:
diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h
index c2ac6a23a74..80c4d7d5548 100644
--- a/clang/Sema/Sema.h
+++ b/clang/Sema/Sema.h
@@ -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,
diff --git a/clang/Sema/SemaDecl.cpp b/clang/Sema/SemaDecl.cpp
index a1402651989..0a63cb9106d 100644
--- a/clang/Sema/SemaDecl.cpp
+++ b/clang/Sema/SemaDecl.cpp
@@ -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,
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 2ede710f524..4fe9f75390e 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -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:
diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h
index f70278a8feb..987bf57cb59 100644
--- a/clang/include/clang/AST/DeclObjC.h
+++ b/clang/include/clang/AST/DeclObjC.h
@@ -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
diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def
index adc2425917b..16fccb62bc2 100644
--- a/clang/include/clang/Basic/DiagnosticKinds.def
+++ b/clang/include/clang/Basic/DiagnosticKinds.def
@@ -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
diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h
index 462192896b5..509e0a28139 100644
--- a/clang/include/clang/Parse/Action.h
+++ b/clang/include/clang/Parse/Action.h
@@ -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(
diff --git a/clang/test/Parser/objc-alias-printing.m b/clang/test/Parser/objc-alias-printing.m
new file mode 100644
index 00000000000..67e013f1d3d
--- /dev/null
+++ b/clang/test/Parser/objc-alias-printing.m
@@ -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;
+}
diff --git a/clang/test/Sema/alias-test-1.m b/clang/test/Sema/alias-test-1.m
new file mode 100644
index 00000000000..27ee196798f
--- /dev/null
+++ b/clang/test/Sema/alias-test-1.m
@@ -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;
+}
OpenPOWER on IntegriCloud