aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaDeclObjC.cpp')
-rw-r--r--lib/Sema/SemaDeclObjC.cpp159
1 files changed, 60 insertions, 99 deletions
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 160bc19b3f..a25aeda150 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -20,50 +20,6 @@
#include "clang/Parse/DeclSpec.h"
using namespace clang;
-/// \brief Look for an Objective-C class in the translation unit.
-///
-/// \param Id The name of the Objective-C class we're looking for. If
-/// typo-correction fixes this name, the Id will be updated
-/// to the fixed name.
-///
-/// \param IdLoc The location of the name in the translation unit.
-///
-/// \param TypoCorrection If true, this routine will attempt typo correction
-/// if there is no class with the given name.
-///
-/// \returns The declaration of the named Objective-C class, which is also the
-/// definition if one is available, or NULL if the class could not be found.
-ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
- SourceLocation IdLoc,
- bool TypoCorrection) {
- // The third "scope" argument is 0 since we aren't enabling lazy built-in
- // creation from this context.
- NamedDecl *Decl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName);
-
- if (!Decl && TypoCorrection) {
- // Perform typo correction at the given location, but only if we
- // find an Objective-C class name.
- LookupResult R(*this, Id, IdLoc, LookupOrdinaryName);
- if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&
- (Decl = R.getAsSingle<ObjCInterfaceDecl>())) {
- Diag(IdLoc, diag::err_undef_interface_suggest)
- << Id << Decl->getDeclName()
- << FixItHint::CreateReplacement(IdLoc, Decl->getNameAsString());
- Diag(Decl->getLocation(), diag::note_previous_decl)
- << Decl->getDeclName();
-
- Id = Decl->getIdentifier();
- }
- }
-
- ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl);
- if (IDecl) {
- if (ObjCInterfaceDecl *Def = IDecl->getDefinition())
- IDecl = Def;
- }
- return IDecl;
-}
-
/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible
/// and user declared, in the method definition's AST.
void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) {
@@ -109,8 +65,6 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
SourceLocation EndProtoLoc, AttributeList *AttrList) {
assert(ClassName && "Missing class identifier");
- bool Invalid = false;
-
// Check for another declaration kind with the same name.
NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc,
LookupOrdinaryName, ForRedeclaration);
@@ -118,34 +72,41 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- // Set the new decl invalid and ignore the old.
- Invalid = true;
- PrevDecl = 0;
}
- ObjCInterfaceDecl *ODecl = cast_or_null<ObjCInterfaceDecl>(PrevDecl);
- if (ODecl) {
+ ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+ if (IDecl) {
// Class already seen. Is it a forward declaration?
- if (ObjCInterfaceDecl *Def = ODecl->getDefinition()) {
- Invalid = true;
- Diag(AtInterfaceLoc, diag::err_duplicate_class_def) << Def->getDeclName();
- Diag(Def->getLocation(), diag::note_previous_definition);
+ if (!IDecl->isForwardDecl()) {
+ IDecl->setInvalidDecl();
+ Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName();
+ Diag(IDecl->getLocation(), diag::note_previous_definition);
- // Return the previous class interface and ignore the new one.
- return DeclPtrTy::make(ODecl);
+ // Return the previous class interface.
+ // FIXME: don't leak the objects passed in!
+ return DeclPtrTy::make(IDecl);
+ } else {
+ IDecl->setLocation(AtInterfaceLoc);
+ IDecl->setForwardDecl(false);
+ IDecl->setClassLoc(ClassLoc);
+
+ // Since this ObjCInterfaceDecl was created by a forward declaration,
+ // we now add it to the DeclContext since it wasn't added before
+ // (see ActOnForwardClassDeclaration).
+ IDecl->setLexicalDeclContext(CurContext);
+ CurContext->addDecl(IDecl);
+
+ if (AttrList)
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
}
- }
-
- ObjCInterfaceDecl *IDecl =
- ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
- ClassName, ClassLoc, ODecl);
- if (Invalid)
- IDecl->setInvalidDecl();
-
- if (AttrList)
- ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+ } else {
+ IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
+ ClassName, ClassLoc);
+ if (AttrList)
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
- PushOnScopeChains(IDecl, TUScope);
+ PushOnScopeChains(IDecl, TUScope);
+ }
if (SuperName) {
// Check if a different kind of symbol declared in this scope.
@@ -164,8 +125,6 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
}
}
- // Since we just pushed IDecl on the scope chain, if PrevDecl is the same
- // class, it will be the same declaration.
if (PrevDecl == IDecl) {
Diag(SuperLoc, diag::err_recursive_superclass)
<< SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
@@ -181,11 +140,11 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
if (PrevDecl && SuperClassDecl == 0) {
// The previous declaration was not a class decl. Check if we have a
// typedef. If we do, get the underlying class type.
- if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)){
+ if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
QualType T = TDecl->getUnderlyingType();
if (T->isObjCObjectType()) {
- if (NamedDecl *NDecl = T->getAs<ObjCObjectType>()->getInterface())
- SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(NDecl);
+ if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface())
+ SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
}
}
@@ -200,11 +159,6 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
}
}
- if (SuperClassDecl) {
- if (ObjCInterfaceDecl *Def = SuperClassDecl->getDefinition())
- SuperClassDecl = Def;
- }
-
if (!dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
if (!SuperClassDecl)
Diag(SuperLoc, diag::err_undef_superclass)
@@ -576,7 +530,7 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperClassname,
SourceLocation SuperClassLoc) {
- ObjCInterfaceDecl *IDecl = 0, *ODecl = 0;
+ ObjCInterfaceDecl* IDecl = 0;
// Check for another declaration kind with the same name.
NamedDecl *PrevDecl
= LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName,
@@ -584,10 +538,11 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- } else if ((ODecl = cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
- // If we can't find a definition of the interface, warn.
- if (!(IDecl = ODecl->getDefinition())) {
+ } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
+ // If this is a forward declaration of an interface, warn.
+ if (IDecl->isForwardDecl()) {
Diag(ClassLoc, diag::warn_undef_interface) << ClassName;
+ IDecl = 0;
}
} else {
// We did not find anything with the name ClassName; try to correct for
@@ -597,7 +552,7 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
(IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
// Suggest the (potentially) correct interface name. However, put the
// fix-it hint itself in a separate note, since changing the name in
- // the warning would make the fix-it change semantics. Also, don't
+ // the warning would make the fix-it change semantics.However, don't
// provide a code-modification hint or use the typo name for recovery,
// because this is just a warning. The program may actually be correct.
Diag(ClassLoc, diag::warn_undef_interface_suggest)
@@ -644,11 +599,16 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
// FIXME: Do we support attributes on the @implementation? If so we should
// copy them over.
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
- ClassName, ClassLoc, ODecl, false, true);
+ ClassName, ClassLoc, false, true);
IDecl->setSuperClass(SDecl);
IDecl->setLocEnd(ClassLoc);
PushOnScopeChains(IDecl, TUScope);
+ } else {
+ // Mark the interface as being completed, even if it was just as
+ // @class ....;
+ // declaration; the user cannot reopen it.
+ IDecl->setForwardDecl(false);
}
ObjCImplementationDecl* IMPDecl =
@@ -659,15 +619,15 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
return DeclPtrTy::make(IMPDecl);
// Check that there is no duplicate implementation of this class.
- if (IDecl && IDecl->getImplementation()) {
+ if (IDecl->getImplementation()) {
+ // FIXME: Don't leak everything!
Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;
Diag(IDecl->getImplementation()->getLocation(),
diag::note_previous_definition);
- } else {
+ } else { // add it to the list.
IDecl->setImplementation(IMPDecl);
PushOnScopeChains(IMPDecl, TUScope);
}
-
return DeclPtrTy::make(IMPDecl);
}
@@ -1069,18 +1029,19 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
PrevDecl = OI->getInterface();
}
}
- ObjCInterfaceDecl *ODecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
- ObjCInterfaceDecl *IDecl =
- ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
- IdentList[i], IdentLocs[i], ODecl, true);
-
- // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to
- // the current DeclContext. This prevents clients that walk DeclContext
- // from seeing the imaginary ObjCInterfaceDecl until it is actually
- // declared later (if at all). We also take care to explicitly make
- // sure this declaration is visible for name lookup.
- PushOnScopeChains(IDecl, TUScope, false);
- CurContext->makeDeclVisibleInContext(IDecl, true);
+ ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+ if (!IDecl) { // Not already seen? Make a forward decl.
+ IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
+ IdentList[i], IdentLocs[i], true);
+
+ // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to
+ // the current DeclContext. This prevents clients that walk DeclContext
+ // from seeing the imaginary ObjCInterfaceDecl until it is actually
+ // declared later (if at all). We also take care to explicitly make
+ // sure this declaration is visible for name lookup.
+ PushOnScopeChains(IDecl, TUScope, false);
+ CurContext->makeDeclVisibleInContext(IDecl, true);
+ }
Interfaces.push_back(IDecl);
}