From: Douglas Gregor Date: Mon, 12 Sep 2011 18:37:38 +0000 (+0000) Subject: Diagnose attempt to mark function-local declarations as __module_private__. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e389585f8a40f80004d3b98b99f3980305ef78a0;p=clang Diagnose attempt to mark function-local declarations as __module_private__. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139519 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 3c9e0f7e03..651a642cc3 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4725,6 +4725,12 @@ def err_module_private_follows_public : Error< def err_module_private_specialization : Error< "%select{template|partial|member}0 specialization cannot be " "declared __module_private__">; +def err_module_private_local : Error< + "%select{local variable|parameter|typedef}0 %1 cannot be declared " + "__module_private__">; +def err_module_private_local_class : Error< + "local %select{struct|union|class|enum}0 cannot be declared " + "__module_private__">; } } // end of sema component. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 432354cc7d..b33294d7c3 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2373,6 +2373,12 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, if (DS.isExplicitSpecified()) Diag(DS.getExplicitSpecLoc(), diag::warn_standalone_specifier) <<"explicit"; + if (DS.isModulePrivateSpecified() && + Tag && Tag->getDeclContext()->isFunctionOrMethod()) + Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class) + << Tag->getTagKind() + << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc()); + // FIXME: Warn on useless attributes return TagD; @@ -3818,6 +3824,10 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } + // Set the lexical context. If the declarator has a C++ scope specifier, the + // lexical context will be different from the semantic context. + NewVD->setLexicalDeclContext(CurContext); + if (D.getDeclSpec().isThreadSpecified()) { if (NewVD->hasLocalStorage()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global); @@ -3832,14 +3842,15 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(NewVD->getLocation(), diag::err_module_private_specialization) << 2 << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + else if (NewVD->hasLocalStorage()) + Diag(NewVD->getLocation(), diag::err_module_private_local) + << 0 << NewVD->getDeclName() + << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); else NewVD->setModulePrivate(); } - // Set the lexical context. If the declarator has a C++ scope specifier, the - // lexical context will be different from the semantic context. - NewVD->setLexicalDeclContext(CurContext); - // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewVD, D); @@ -6357,6 +6368,12 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { ProcessDeclAttributes(S, New, D); + if (D.getDeclSpec().isModulePrivateSpecified()) + Diag(New->getLocation(), diag::err_module_private_local) + << 1 << New->getDeclName() + << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + if (New->hasAttr()) { Diag(New->getLocation(), diag::err_block_on_nonlocal); } @@ -7021,8 +7038,15 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, return NewTD; } - if (D.getDeclSpec().isModulePrivateSpecified()) - NewTD->setModulePrivate(); + if (D.getDeclSpec().isModulePrivateSpecified()) { + if (CurContext->isFunctionOrMethod()) + Diag(NewTD->getLocation(), diag::err_module_private_local) + << 2 << NewTD->getDeclName() + << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + else + NewTD->setModulePrivate(); + } // C++ [dcl.typedef]p8: // If the typedef declaration defines an unnamed class (or @@ -7777,7 +7801,11 @@ CreateNewDecl: << FixItHint::CreateRemoval(ModulePrivateLoc); else if (PrevDecl && !PrevDecl->isModulePrivate()) diagnoseModulePrivateRedeclaration(New, PrevDecl, ModulePrivateLoc); - else + // __module_private__ does not apply to local classes. However, we only + // diagnose this as an error when the declaration specifiers are + // freestanding. Here, we just ignore the __module_private__. + // foobar + else if (!SearchDC->isFunctionOrMethod()) New->setModulePrivate(); } diff --git a/test/Modules/module-private.cpp b/test/Modules/module-private.cpp index 949d795865..33ec32048a 100644 --- a/test/Modules/module-private.cpp +++ b/test/Modules/module-private.cpp @@ -119,4 +119,14 @@ __module_private__ struct public_class { }; // expected-error{{template s template __module_private__ struct public_class { }; // expected-error{{partial specialization cannot be declared __module_private__}} +// Check for attempts to make parameters and variables with automatic +// storage module-private. + +void local_var_private(__module_private__ int param) { // expected-error{{parameter 'param' cannot be declared __module_private__}} + __module_private__ struct Local { int x, y; } local; //expected-error{{local variable 'local' cannot be declared __module_private__}} + + __module_private__ struct OtherLocal { int x; }; // expected-error{{local struct cannot be declared __module_private__}} + + typedef __module_private__ int local_typedef; // expected-error{{typedef 'local_typedef' cannot be declared __module_private__}} +} #endif