forked from OSchip/llvm-project
rename Decl::CompatibleAlias -> ObjCCompatibleAlias.
Fix objc ivar lookup. Ivar lookup should occur between lookup of method-local values and lookup of globals. Emulate this with some logic in the handling of Sema::ActOnIdentifierExpr. Two todo's left: 1) sema shouldn't turn a bare reference to an ivar into "self->ivar" in the AST. This is a hack. 2) The new ScopedDecl::isDefinedOutsideFunctionOrMethod method does not correctly handle typedefs and enum constants yet. llvm-svn: 48972
This commit is contained in:
parent
f2b0b0eb17
commit
59a2594f3f
|
@ -51,7 +51,7 @@ public:
|
|||
ObjCProtocol,
|
||||
PropertyDecl,
|
||||
// ScopedDecl
|
||||
CompatibleAlias,
|
||||
ObjCCompatibleAlias,
|
||||
// TypeDecl
|
||||
ObjCInterface,
|
||||
Typedef,
|
||||
|
@ -78,7 +78,7 @@ public:
|
|||
// of the class, to allow efficient classof.
|
||||
NamedFirst = Field, NamedLast = ParmVar,
|
||||
FieldFirst = Field, FieldLast = ObjCIvar,
|
||||
ScopedFirst = CompatibleAlias, ScopedLast = ParmVar,
|
||||
ScopedFirst = ObjCCompatibleAlias, ScopedLast = ParmVar,
|
||||
TypeFirst = ObjCInterface, TypeLast = Class,
|
||||
TagFirst = Enum , TagLast = Class,
|
||||
RecordFirst = Struct , RecordLast = Class,
|
||||
|
@ -161,7 +161,7 @@ public:
|
|||
case ParmVar:
|
||||
case EnumConstant:
|
||||
case ObjCInterface:
|
||||
case CompatibleAlias:
|
||||
case ObjCCompatibleAlias:
|
||||
return IDNS_Ordinary;
|
||||
case Struct:
|
||||
case Union:
|
||||
|
@ -247,6 +247,12 @@ public:
|
|||
const ScopedDecl *getNextDeclarator() const { return NextDeclarator; }
|
||||
void setNextDeclarator(ScopedDecl *N) { NextDeclarator = N; }
|
||||
|
||||
// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
|
||||
// scoped decl is defined outside the current function or method. This is
|
||||
// roughly global variables and functions, but also handles enums (which could
|
||||
// be defined inside or outside a function etc).
|
||||
bool isDefinedOutsideFunctionOrMethod() const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= ScopedFirst && D->getKind() <= ScopedLast;
|
||||
|
@ -348,7 +354,11 @@ protected:
|
|||
virtual void ReadImpl(llvm::Deserializer& S);
|
||||
};
|
||||
|
||||
/// BlockVarDecl - Represent a local variable declaration.
|
||||
/// BlockVarDecl - Represent a local variable declaration. Note that this
|
||||
/// includes static variables inside of functions.
|
||||
///
|
||||
/// void foo() { int x; static int y; extern int z; }
|
||||
///
|
||||
class BlockVarDecl : public VarDecl {
|
||||
BlockVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S,
|
||||
ScopedDecl *PrevDecl)
|
||||
|
|
|
@ -877,7 +877,7 @@ class ObjCCompatibleAliasDecl : public ScopedDecl {
|
|||
|
||||
ObjCCompatibleAliasDecl(SourceLocation L, IdentifierInfo *Id,
|
||||
ObjCInterfaceDecl* aliasedClass)
|
||||
: ScopedDecl(CompatibleAlias, L, Id, 0), AliasedClass(aliasedClass) {}
|
||||
: ScopedDecl(ObjCCompatibleAlias, L, Id, 0), AliasedClass(aliasedClass) {}
|
||||
public:
|
||||
static ObjCCompatibleAliasDecl *Create(ASTContext &C, SourceLocation L,
|
||||
IdentifierInfo *Id,
|
||||
|
@ -887,7 +887,7 @@ public:
|
|||
ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == CompatibleAlias;
|
||||
return D->getKind() == ObjCCompatibleAlias;
|
||||
}
|
||||
static bool classof(const ObjCCompatibleAliasDecl *D) { return true; }
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ void Decl::addDeclKind(Kind k) {
|
|||
case ObjCIvar: nIvarDecls++; break;
|
||||
case ObjCImplementation: nObjCImplementationDecls++; break;
|
||||
case ObjCCategoryImpl: nObjCCategoryImpl++; break;
|
||||
case CompatibleAlias: nObjCCompatibleAlias++; break;
|
||||
case ObjCCompatibleAlias: nObjCCompatibleAlias++; break;
|
||||
case PropertyDecl: nObjCPropertyDecl++; break;
|
||||
case LinkageSpec: nLinkageSpecDecl++; break;
|
||||
case FileScopeAsm: nFileScopeAsmDecl++; break;
|
||||
|
@ -319,12 +319,46 @@ const Attr *Decl::getAttrs() const {
|
|||
return (*DeclAttrs)[this];
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// NamedDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
const char *NamedDecl::getName() const {
|
||||
if (const IdentifierInfo *II = getIdentifier())
|
||||
return II->getName();
|
||||
return "";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ScopedDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
|
||||
// scoped decl is defined outside the current function or method. This is
|
||||
// roughly global variables and functions, but also handles enums (which could
|
||||
// be defined inside or outside a function etc).
|
||||
bool ScopedDecl::isDefinedOutsideFunctionOrMethod() const {
|
||||
if (const VarDecl *VD = dyn_cast<VarDecl>(this))
|
||||
return VD->hasGlobalStorage();
|
||||
if (isa<FunctionDecl>(this))
|
||||
return true;
|
||||
|
||||
// FIXME: Why is ObjCCompatibleAlias a scopedecl?
|
||||
if (isa<ObjCCompatibleAliasDecl>(this))
|
||||
return true;
|
||||
|
||||
// FIXME: This needs to check the context the decl was defined in!
|
||||
if (isa<TypeDecl>(this) || isa<EnumConstantDecl>(this))
|
||||
return true;
|
||||
|
||||
assert(0 && "Unknown ScopedDecl!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FunctionDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
FunctionDecl::~FunctionDecl() {
|
||||
delete[] ParamInfo;
|
||||
}
|
||||
|
@ -346,6 +380,9 @@ void FunctionDecl::setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) {
|
|||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// RecordDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// defineBody - When created, RecordDecl's correspond to a forward declared
|
||||
/// record. This method is used to mark the decl as being defined, with the
|
||||
|
@ -360,14 +397,13 @@ void RecordDecl::defineBody(FieldDecl **members, unsigned numMembers) {
|
|||
}
|
||||
}
|
||||
|
||||
FieldDecl* RecordDecl::getMember(IdentifierInfo *name) {
|
||||
FieldDecl *RecordDecl::getMember(IdentifierInfo *II) {
|
||||
if (Members == 0 || NumMembers < 0)
|
||||
return 0;
|
||||
|
||||
// linear search. When C++ classes come along, will likely need to revisit.
|
||||
for (int i = 0; i < NumMembers; ++i) {
|
||||
if (Members[i]->getIdentifier() == name)
|
||||
// Linear search. When C++ classes come along, will likely need to revisit.
|
||||
for (int i = 0; i != NumMembers; ++i)
|
||||
if (Members[i]->getIdentifier() == II)
|
||||
return Members[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -74,31 +74,43 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
|
|||
Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
|
||||
IdentifierInfo &II,
|
||||
bool HasTrailingLParen) {
|
||||
// Could be enum-constant or decl.
|
||||
// Could be enum-constant, value decl, instance variable, etc.
|
||||
ScopedDecl *D = LookupScopedDecl(&II, Decl::IDNS_Ordinary, Loc, S);
|
||||
|
||||
// If this reference is in an Objective-C method, then ivar lookup happens as
|
||||
// well.
|
||||
if (CurMethodDecl) {
|
||||
// There are two cases to handle here. 1) scoped lookup could have failed,
|
||||
// in which case we should look for an ivar. 2) scoped lookup could have
|
||||
// found a decl, but that decl is outside the current method (i.e. a global
|
||||
// variable). In these two cases, we do a lookup for an ivar with this
|
||||
// name, if the lookup suceeds, we replace it our current decl.
|
||||
if (D == 0 || D->isDefinedOutsideFunctionOrMethod()) {
|
||||
ObjCInterfaceDecl *IFace = CurMethodDecl->getClassInterface(), *DeclClass;
|
||||
if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(&II, DeclClass)) {
|
||||
// FIXME: This should use a new expr for a direct reference, don't turn
|
||||
// this into Self->ivar, just return a BareIVarExpr or something.
|
||||
IdentifierInfo &II = Context.Idents.get("self");
|
||||
ExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false);
|
||||
return new ObjCIvarRefExpr(IV, IV->getType(), Loc,
|
||||
static_cast<Expr*>(SelfExpr.Val), true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (D == 0) {
|
||||
// Otherwise, this could be an implicitly declared function reference (legal
|
||||
// in C90, extension in C99).
|
||||
if (HasTrailingLParen &&
|
||||
// Not in C++.
|
||||
!getLangOptions().CPlusPlus)
|
||||
!getLangOptions().CPlusPlus) // Not in C++.
|
||||
D = ImplicitlyDefineFunction(Loc, II, S);
|
||||
else {
|
||||
if (CurMethodDecl) {
|
||||
ObjCInterfaceDecl *IFace = CurMethodDecl->getClassInterface();
|
||||
ObjCInterfaceDecl *clsDeclared;
|
||||
if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(&II, clsDeclared)) {
|
||||
IdentifierInfo &II = Context.Idents.get("self");
|
||||
ExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false);
|
||||
return new ObjCIvarRefExpr(IV, IV->getType(), Loc,
|
||||
static_cast<Expr*>(SelfExpr.Val), true, true);
|
||||
}
|
||||
}
|
||||
// If this name wasn't predeclared and if this is not a function call,
|
||||
// diagnose the problem.
|
||||
return Diag(Loc, diag::err_undeclared_var_use, II.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
|
||||
// check if referencing an identifier with __attribute__((deprecated)).
|
||||
if (VD->getAttr<DeprecatedAttr>())
|
||||
|
@ -109,6 +121,7 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
|
|||
return true;
|
||||
return new DeclRefExpr(VD, VD->getType(), Loc);
|
||||
}
|
||||
|
||||
if (isa<TypedefDecl>(D))
|
||||
return Diag(Loc, diag::err_unexpected_typedef, II.getName());
|
||||
if (isa<ObjCInterfaceDecl>(D))
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// RUN: clang %s -fsyntax-only -verify
|
||||
|
||||
@interface Test {
|
||||
int x;
|
||||
}
|
||||
|
||||
-(void) setX: (int) d;
|
||||
@end
|
||||
|
||||
extern struct foo x;
|
||||
|
||||
@implementation Test
|
||||
|
||||
-(void) setX: (int) n {
|
||||
x = n;
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue