From: Anders Carlsson Date: Tue, 4 Nov 2008 16:57:32 +0000 (+0000) Subject: Make it an error if an Objective-C declaration is not in the global scope. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=15281450f512b7d554858e4d17fca00bfc442a07;p=clang Make it an error if an Objective-C declaration is not in the global scope. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58705 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 32f52f41cb..8517222c1d 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -696,6 +696,10 @@ DIAG(err_reference_var_requires_init, ERROR, DIAG(err_const_var_requires_init, ERROR, "declaration of const variable '%0' requires an initializer") +// Objective-C++ +DIAG(err_objc_decls_may_only_appear_in_global_scope, ERROR, + "Objective-C declarations may only appear in global scope") + // Attributes DIAG(err_attribute_wrong_number_arguments, ERROR, "attribute requires %0 argument(s)") diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index a3d73c4c93..ce70855a37 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1209,7 +1209,11 @@ private: bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, bool ForCompare); - + /// Checks that the Objective-C declaration is declared in the global scope. + /// Emits an error and marks the declaration as invalid if it's not declared + /// in the global scope. + bool CheckObjCDeclScope(Decl *D); + void InitBuiltinVaListType(); // Helper method to turn variable array types into diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 3ccea6e082..6c17d5f1f6 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -124,6 +124,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IDecl->addReferencedProtocols((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs); IDecl->setLocEnd(EndProtoLoc); } + + CheckObjCDeclScope(IDecl); return IDecl; } @@ -163,7 +165,10 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, ObjCCompatibleAliasDecl::Create(Context, AtLoc, AliasName, CDecl); ObjCAliasDecls[AliasName] = AliasDecl; - TUScope->AddDecl(AliasDecl); + + if (!CheckObjCDeclScope(AliasDecl)) + TUScope->AddDecl(AliasDecl); + return AliasDecl; } @@ -201,6 +206,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, PDecl->addReferencedProtocols((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs); PDecl->setLocEnd(EndProtoLoc); } + + CheckObjCDeclScope(PDecl); return PDecl; } @@ -370,8 +377,13 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, Protocols.push_back(PDecl); } - return ObjCForwardProtocolDecl::Create(Context, AtProtocolLoc, - &Protocols[0], Protocols.size()); + + ObjCForwardProtocolDecl *PDecl = + ObjCForwardProtocolDecl::Create(Context, AtProtocolLoc, + &Protocols[0], Protocols.size()); + + CheckObjCDeclScope(PDecl); + return PDecl; } Sema::DeclTy *Sema:: @@ -410,6 +422,8 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, CDecl->addReferencedProtocols((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs); CDecl->setLocEnd(EndProtoLoc); } + + CheckObjCDeclScope(CDecl); return CDecl; } @@ -430,6 +444,8 @@ Sema::DeclTy *Sema::ActOnStartCategoryImplementation( /// TODO: Check that CatName, category name, is not used in another // implementation. ObjCCategoryImpls.push_back(CDecl); + + CheckObjCDeclScope(CDecl); return CDecl; } @@ -498,6 +514,9 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation( ObjCImplementationDecl::Create(Context, AtClassImplLoc, ClassName, IDecl, SDecl); + if (CheckObjCDeclScope(IMPDecl)) + return IMPDecl; + // Check that there is no duplicate implementation of this class. if (ObjCImplementations[ClassName]) // FIXME: Don't leak everything! @@ -730,8 +749,12 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, Interfaces.push_back(IDecl); } - return ObjCClassDecl::Create(Context, AtClassLoc, - &Interfaces[0], Interfaces.size()); + ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, AtClassLoc, + &Interfaces[0], + Interfaces.size()); + + CheckObjCDeclScope(CDecl); + return CDecl; } @@ -1327,3 +1350,14 @@ Sema::DeclTy *Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, return PIDecl; } + +bool Sema::CheckObjCDeclScope(Decl *D) +{ + if (isa(CurContext)) + return false; + + Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope); + D->setInvalidDecl(); + + return true; +} diff --git a/test/SemaObjCXX/objc-decls-inside-namespace.mm b/test/SemaObjCXX/objc-decls-inside-namespace.mm new file mode 100644 index 0000000000..3ad3508c0a --- /dev/null +++ b/test/SemaObjCXX/objc-decls-inside-namespace.mm @@ -0,0 +1,27 @@ +// RUN: clang -fsyntax-only -verify %s + +namespace C { + +@protocol P; //expected-error{{Objective-C declarations may only appear in global scope}} + +@class Bar; //expected-error{{Objective-C declarations may only appear in global scope}} + +@compatibility_alias Foo Bar; //expected-error{{Objective-C declarations may only appear in global scope}} + +@interface A //expected-error{{Objective-C declarations may only appear in global scope}} +@end + +@implementation A //expected-error{{Objective-C declarations may only appear in global scope}} +@end + +@protocol P //expected-error{{Objective-C declarations may only appear in global scope}} +@end + +@interface A(C) //expected-error{{Objective-C declarations may only appear in global scope}} +@end + +@implementation A(C) //expected-error{{Objective-C declarations may only appear in global scope}} +@end + +} +