aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.cpp2
-rw-r--r--lib/Sema/SemaCodeComplete.cpp26
-rw-r--r--lib/Sema/SemaDecl.cpp39
-rw-r--r--lib/Sema/SemaDeclObjC.cpp159
4 files changed, 117 insertions, 109 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index aeb4db987d..11d7a9191f 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -89,7 +89,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
ObjCInterfaceDecl *ProtocolDecl =
ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
&Context.Idents.get("Protocol"),
- SourceLocation(), true);
+ SourceLocation(), 0, true);
Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
PushOnScopeChains(ProtocolDecl, TUScope, false);
}
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 52ac8dd649..f12e1839e5 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -3748,20 +3748,28 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
for (DeclContext::decl_iterator D = Ctx->decls_begin(),
DEnd = Ctx->decls_end();
D != DEnd; ++D) {
- // Record any interfaces we find.
- if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
- if ((!OnlyForwardDeclarations || Class->isForwardDecl()) &&
- (!OnlyUnimplemented || !Class->getImplementation()))
- Results.AddResult(Result(Class, 0), CurContext, 0, false);
+ // Record any interfaces we find. Forward declarations are never registered
+ // in the lexical contest, so if we're only looking for those, don't bother.
+ if (!OnlyForwardDeclarations)
+ if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
+ if (!OnlyUnimplemented || !Class->getImplementation())
+ Results.AddResult(Result(Class, 0), CurContext, 0, false);
// Record any forward-declared interfaces we find.
if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end();
- C != CEnd; ++C)
- if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) &&
- (!OnlyUnimplemented || !C->getInterface()->getImplementation()))
- Results.AddResult(Result(C->getInterface(), 0), CurContext,
+ C != CEnd; ++C) {
+ ObjCInterfaceDecl *IDecl = C->getInterface();
+ ObjCInterfaceDecl *IDef = IDecl->getDefinition();
+ // If there's a definition, and we're looking for everything, then we
+ // already added the decl in question above.
+ if (!OnlyForwardDeclarations && !OnlyUnimplemented && IDef)
+ continue;
+ if ((!OnlyForwardDeclarations || !IDef) &&
+ (!OnlyUnimplemented || !IDef || !IDef->getImplementation()))
+ Results.AddResult(Result(IDecl, 0), CurContext,
0, false);
+ }
}
}
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 200b8fd681..e6c5170357 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -606,45 +606,6 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
}
}
-/// \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, 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 *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName);
-
- if (!IDecl && 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) &&
- (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
- Diag(IdLoc, diag::err_undef_interface_suggest)
- << Id << IDecl->getDeclName()
- << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString());
- Diag(IDecl->getLocation(), diag::note_previous_decl)
- << IDecl->getDeclName();
-
- Id = IDecl->getIdentifier();
- }
- }
-
- return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
-}
-
/// getNonFieldDeclScope - Retrieves the innermost scope, starting
/// from S, where a non-field would be declared. This routine copes
/// with the difference between C and C++ scoping rules in structs and
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 9e0d250536..283376bfde 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -20,6 +20,50 @@
#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) {
@@ -65,6 +109,8 @@ 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);
@@ -72,42 +118,35 @@ 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* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
- if (IDecl) {
+ ObjCInterfaceDecl *ODecl = cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+ if (ODecl) {
// Class already seen. Is it a forward declaration?
- if (!IDecl->isForwardDecl()) {
- IDecl->setInvalidDecl();
- Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName();
- Diag(IDecl->getLocation(), diag::note_previous_definition);
+ if (ObjCInterfaceDecl *Def = ODecl->getDefinition()) {
+ Invalid = true;
+ Diag(AtInterfaceLoc, diag::err_duplicate_class_def) << Def->getDeclName();
+ Diag(Def->getLocation(), diag::note_previous_definition);
- // 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);
+ // Return the previous class interface and ignore the new one.
+ return DeclPtrTy::make(ODecl);
}
- } else {
- IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
- ClassName, ClassLoc);
- if (AttrList)
- ProcessDeclAttributeList(TUScope, IDecl, AttrList);
-
- PushOnScopeChains(IDecl, TUScope);
}
+ ObjCInterfaceDecl *IDecl =
+ ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
+ ClassName, ClassLoc, ODecl);
+ if (Invalid)
+ IDecl->setInvalidDecl();
+
+ if (AttrList)
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+
+ PushOnScopeChains(IDecl, TUScope);
+
if (SuperName) {
// Check if a different kind of symbol declared in this scope.
PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
@@ -125,6 +164,8 @@ 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);
@@ -140,11 +181,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 *IDecl = T->getAs<ObjCObjectType>()->getInterface())
- SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
+ if (NamedDecl *NDecl = T->getAs<ObjCObjectType>()->getInterface())
+ SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(NDecl);
}
}
@@ -159,6 +200,11 @@ 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)
@@ -530,7 +576,7 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperClassname,
SourceLocation SuperClassLoc) {
- ObjCInterfaceDecl* IDecl = 0;
+ ObjCInterfaceDecl *IDecl = 0, *ODecl = 0;
// Check for another declaration kind with the same name.
NamedDecl *PrevDecl
= LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName,
@@ -538,11 +584,10 @@ 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 ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
- // If this is a forward declaration of an interface, warn.
- if (IDecl->isForwardDecl()) {
+ } else if ((ODecl = cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
+ // If we can't find a definition of the interface, warn.
+ if (!(IDecl = ODecl->getDefinition())) {
Diag(ClassLoc, diag::warn_undef_interface) << ClassName;
- IDecl = 0;
}
} else {
// We did not find anything with the name ClassName; try to correct for
@@ -552,7 +597,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.However, don't
+ // the warning would make the fix-it change semantics. Also, 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)
@@ -599,16 +644,11 @@ 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, false, true);
+ ClassName, ClassLoc, ODecl, 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 =
@@ -619,15 +659,15 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
return DeclPtrTy::make(IMPDecl);
// Check that there is no duplicate implementation of this class.
- if (IDecl->getImplementation()) {
- // FIXME: Don't leak everything!
+ if (IDecl && IDecl->getImplementation()) {
Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;
Diag(IDecl->getImplementation()->getLocation(),
diag::note_previous_definition);
- } else { // add it to the list.
+ } else {
IDecl->setImplementation(IMPDecl);
PushOnScopeChains(IMPDecl, TUScope);
}
+
return DeclPtrTy::make(IMPDecl);
}
@@ -1029,19 +1069,18 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
PrevDecl = OI->getInterface();
}
}
- 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);
- }
+ 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);
Interfaces.push_back(IDecl);
}