diff options
| -rw-r--r-- | clang/include/clang/Sema/Lookup.h | 33 | ||||
| -rw-r--r-- | clang/lib/AST/Decl.cpp | 34 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 22 | ||||
| -rw-r--r-- | clang/test/Index/linkage.c | 2 | ||||
| -rw-r--r-- | clang/test/Index/usrs.m | 2 | ||||
| -rw-r--r-- | clang/test/Modules/Inputs/no-linkage/decls.h | 6 | ||||
| -rw-r--r-- | clang/test/Modules/Inputs/no-linkage/empty.h | 0 | ||||
| -rw-r--r-- | clang/test/Modules/Inputs/no-linkage/module.modulemap | 1 | ||||
| -rw-r--r-- | clang/test/Modules/decldef.m | 8 | ||||
| -rw-r--r-- | clang/test/Modules/merge-enumerators.cpp | 8 | ||||
| -rw-r--r-- | clang/test/Modules/module-private.cpp | 6 | ||||
| -rw-r--r-- | clang/test/Modules/no-linkage.cpp | 35 | ||||
| -rw-r--r-- | clang/test/Modules/submodule-visibility-cycles.cpp | 2 | ||||
| -rw-r--r-- | clang/test/Modules/submodules-merge-defs.cpp | 22 |
15 files changed, 115 insertions, 72 deletions
diff --git a/clang/include/clang/Sema/Lookup.h b/clang/include/clang/Sema/Lookup.h index 1162a1d65ab..f291a8aef05 100644 --- a/clang/include/clang/Sema/Lookup.h +++ b/clang/include/clang/Sema/Lookup.h @@ -139,8 +139,7 @@ public: Redecl(Redecl != Sema::NotForRedeclaration), HideTags(true), Diagnose(Redecl == Sema::NotForRedeclaration), - AllowHidden(Redecl == Sema::ForRedeclaration), - AllowHiddenInternal(AllowHidden), + AllowHidden(false), Shadowed(false) { configure(); @@ -162,8 +161,7 @@ public: Redecl(Redecl != Sema::NotForRedeclaration), HideTags(true), Diagnose(Redecl == Sema::NotForRedeclaration), - AllowHidden(Redecl == Sema::ForRedeclaration), - AllowHiddenInternal(AllowHidden), + AllowHidden(false), Shadowed(false) { configure(); @@ -184,7 +182,6 @@ public: HideTags(Other.HideTags), Diagnose(false), AllowHidden(Other.AllowHidden), - AllowHiddenInternal(Other.AllowHiddenInternal), Shadowed(false) {} @@ -226,27 +223,16 @@ public: /// \brief Specify whether hidden declarations are visible, e.g., /// for recovery reasons. void setAllowHidden(bool AH) { - AllowHiddenInternal = AllowHidden = AH; - } - - /// \brief Specify whether hidden internal declarations are visible. - void setAllowHiddenInternal(bool AHI) { - AllowHiddenInternal = AHI; + AllowHidden = AH; } /// \brief Determine whether this lookup is permitted to see hidden /// declarations, such as those in modules that have not yet been imported. bool isHiddenDeclarationVisible(NamedDecl *ND) const { - // If a using-shadow declaration is hidden, it's never visible, not - // even to redeclaration lookup. - // FIXME: Should this apply to typedefs and namespace aliases too? - if (isa<UsingShadowDecl>(ND) && LookupKind != Sema::LookupUsingDeclName) - return false; - return (AllowHidden && - (AllowHiddenInternal || ND->isExternallyVisible())) || - LookupKind == Sema::LookupTagName; + return AllowHidden || + (isForRedeclaration() && ND->isExternallyVisible()); } - + /// Sets whether tag declarations should be hidden by non-tag /// declarations during resolution. The default is true. void setHideTags(bool Hide) { @@ -317,7 +303,8 @@ public: if (!D->isInIdentifierNamespace(IDNS)) return nullptr; - if (isHiddenDeclarationVisible(D) || isVisible(getSema(), D)) + if (!D->isHidden() || isHiddenDeclarationVisible(D) || + isVisibleSlow(getSema(), D)) return D; return getAcceptableDeclSlow(D); @@ -526,7 +513,6 @@ public: /// \brief Change this lookup's redeclaration kind. void setRedeclarationKind(Sema::RedeclarationKind RK) { Redecl = RK; - AllowHiddenInternal = AllowHidden = (RK == Sema::ForRedeclaration); configure(); } @@ -698,9 +684,6 @@ private: /// \brief True if we should allow hidden declarations to be 'visible'. bool AllowHidden; - /// \brief True if we should allow hidden internal declarations to be visible. - bool AllowHiddenInternal; - /// \brief True if the found declarations were shadowed by some other /// declaration that we skipped. This only happens when \c LookupKind /// is \c LookupRedeclarationWithLinkage. diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 0f6e8b09706..8c50af615cd 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -635,6 +635,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (D->isInAnonymousNamespace()) { const auto *Var = dyn_cast<VarDecl>(D); const auto *Func = dyn_cast<FunctionDecl>(D); + // FIXME: In C++11 onwards, anonymous namespaces should give decls + // within them internal linkage, not unique external linkage. if ((!Var || !isFirstInExternCContext(Var)) && (!Func || !isFirstInExternCContext(Func))) return LinkageInfo::uniqueExternal(); @@ -821,10 +823,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, } else if (isa<ObjCInterfaceDecl>(D)) { // fallout + } else if (auto *TD = dyn_cast<TypedefNameDecl>(D)) { + // A typedef declaration has linkage if it gives a type a name for + // linkage purposes. + if (!TD->getAnonDeclWithTypedefName(/*AnyRedecl*/true)) + return LinkageInfo::none(); + // Everything not covered here has no linkage. } else { - // FIXME: A typedef declaration has linkage if it gives a type a name for - // linkage purposes. return LinkageInfo::none(); } @@ -1226,8 +1232,32 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, switch (D->getKind()) { default: break; + + // Per C++ [basic.link]p2, only the names of objects, references, + // functions, types, templates, namespaces, and values ever have linkage. + // + // Note that the name of a typedef, namespace alias, using declaration, + // and so on are not the name of the corresponding type, namespace, or + // declaration, so they do *not* have linkage. + case Decl::EnumConstant: // FIXME: This has linkage, but that's dumb. + case Decl::ImplicitParam: + case Decl::Label: + case Decl::NamespaceAlias: case Decl::ParmVar: + case Decl::Using: + case Decl::UsingShadow: + case Decl::UsingDirective: return LinkageInfo::none(); + + case Decl::Typedef: + case Decl::TypeAlias: + // A typedef declaration has linkage if it gives a type a name for + // linkage purposes. + if (!cast<TypedefNameDecl>(D) + ->getAnonDeclWithTypedefName(/*AnyRedecl*/true)) + return LinkageInfo::none(); + break; + case Decl::TemplateTemplateParm: // count these as external case Decl::NonTypeTemplateParm: case Decl::ObjCAtDefsField: diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 728697e78f5..a23d9debb86 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4819,12 +4819,6 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); - // If we're hiding internal-linkage symbols in modules from redeclaration - // lookup, let name lookup know. - if ((getLangOpts().Modules || getLangOpts().ModulesLocalVisibility) && - D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef) - Previous.setAllowHiddenInternal(false); - // See if this is a redefinition of a variable in the same scope. if (!D.getCXXScopeSpec().isSet()) { bool IsLinkageLookup = false; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 74bffb2a044..910ebcf05dd 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7206,23 +7206,13 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // treated as an original-namespace-name. // // Since namespace names are unique in their scope, and we don't - // look through using directives, just look for any ordinary names. - - const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member | - Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | - Decl::IDNS_Namespace; - NamedDecl *PrevDecl = nullptr; - DeclContext::lookup_result R = CurContext->getRedeclContext()->lookup(II); - for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; - ++I) { - if ((*I)->getIdentifierNamespace() & IDNS) { - PrevDecl = *I; - break; - } - } - + // look through using directives, just look for any ordinary names + // as if by qualified name lookup. + LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, ForRedeclaration); + LookupQualifiedName(R, CurContext->getRedeclContext()); + NamedDecl *PrevDecl = R.getAsSingle<NamedDecl>(); PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl); - + if (PrevNS) { // This is an extended namespace definition. if (IsInline != PrevNS->isInline()) diff --git a/clang/test/Index/linkage.c b/clang/test/Index/linkage.c index ab006590b61..b0dcb30990a 100644 --- a/clang/test/Index/linkage.c +++ b/clang/test/Index/linkage.c @@ -20,7 +20,7 @@ void f16(void) { // CHECK: EnumDecl=Baz:3:6 (Definition)linkage=External -// CHECK: EnumConstantDecl=Qux:3:12 (Definition)linkage=External +// CHECK: EnumConstantDecl=Qux:3:12 (Definition)linkage=NoLinkage // CHECK: VarDecl=x:4:5linkage=External // CHECK: FunctionDecl=foo:5:6linkage=External // CHECK: VarDecl=w:6:12linkage=Internal diff --git a/clang/test/Index/usrs.m b/clang/test/Index/usrs.m index fc3fbc91057..aa0c4a04fc7 100644 --- a/clang/test/Index/usrs.m +++ b/clang/test/Index/usrs.m @@ -119,7 +119,7 @@ int test_multi_declaration(void) { // CHECK: usrs.m c:@SA@MyStruct Extent=[15:9 - 18:2] // CHECK: usrs.m c:@SA@MyStruct@FI@wa Extent=[16:3 - 16:9] // CHECK: usrs.m c:@SA@MyStruct@FI@moo Extent=[17:3 - 17:10] -// CHECK: usrs.m c:usrs.m@T@MyStruct Extent=[15:1 - 18:11] +// CHECK: usrs.m c:@T@MyStruct Extent=[15:1 - 18:11] // CHECK: usrs.m c:@E@Pizza Extent=[20:1 - 23:2] // CHECK: usrs.m c:@E@Pizza@CHEESE Extent=[21:3 - 21:9] // CHECK: usrs.m c:@E@Pizza@MUSHROOMS Extent=[22:3 - 22:12] diff --git a/clang/test/Modules/Inputs/no-linkage/decls.h b/clang/test/Modules/Inputs/no-linkage/decls.h new file mode 100644 index 00000000000..5c29044abf8 --- /dev/null +++ b/clang/test/Modules/Inputs/no-linkage/decls.h @@ -0,0 +1,6 @@ +namespace RealNS { int UsingDecl; } +namespace NS = RealNS; +typedef int Typedef; +using AliasDecl = int; +enum Enum { Enumerator }; +using RealNS::UsingDecl; diff --git a/clang/test/Modules/Inputs/no-linkage/empty.h b/clang/test/Modules/Inputs/no-linkage/empty.h new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/clang/test/Modules/Inputs/no-linkage/empty.h diff --git a/clang/test/Modules/Inputs/no-linkage/module.modulemap b/clang/test/Modules/Inputs/no-linkage/module.modulemap new file mode 100644 index 00000000000..3931b0fe8e7 --- /dev/null +++ b/clang/test/Modules/Inputs/no-linkage/module.modulemap @@ -0,0 +1 @@ +module M { module E { header "empty.h" } module D { header "decls.h" } } diff --git a/clang/test/Modules/decldef.m b/clang/test/Modules/decldef.m index 420c6774ecb..784743ff6e7 100644 --- a/clang/test/Modules/decldef.m +++ b/clang/test/Modules/decldef.m @@ -11,7 +11,13 @@ Def *def; #ifdef USE_EARLY A *a1; // expected-error{{declaration of 'A' must be imported from module 'decldef.Def' before it is required}} #endif -B *b1; // expected-error{{must use 'struct' tag to refer to type 'B'}} +B *b1; +#ifdef USE_EARLY +// expected-error@-2{{must use 'struct' tag to refer to type 'B'}} +#else +// expected-error@-4{{declaration of 'B' must be imported from module 'decldef.Decl' before it is required}} +// expected-note@Inputs/decl.h:2 {{previous}} +#endif @import decldef.Decl; A *a2; diff --git a/clang/test/Modules/merge-enumerators.cpp b/clang/test/Modules/merge-enumerators.cpp index 5267ac658b8..10e1914bd7b 100644 --- a/clang/test/Modules/merge-enumerators.cpp +++ b/clang/test/Modules/merge-enumerators.cpp @@ -16,11 +16,13 @@ #ifdef MERGE_LATE namespace N { - // FIXME: Should we accept this and reject the usage below due to ambiguity instead? - enum { A } a; // expected-error {{redefinition of enumerator 'A'}} - // expected-note@a.h:1 {{here}} (from module B.b) + enum { A } a; // expected-note {{candidate}} + // expected-note@a.h:1 {{candidate}} (from module B.b) } #include "a.h" #endif N::E e = N::A; +#ifdef MERGE_LATE +// expected-error@-2 {{ambiguous}} +#endif diff --git a/clang/test/Modules/module-private.cpp b/clang/test/Modules/module-private.cpp index 6e723c863ce..42ab185760b 100644 --- a/clang/test/Modules/module-private.cpp +++ b/clang/test/Modules/module-private.cpp @@ -12,11 +12,7 @@ void test() { } int test_broken() { - HiddenStruct hidden; // \ - // expected-error{{must use 'struct' tag to refer to type 'HiddenStruct' in this scope}} \ - // expected-error{{definition of 'HiddenStruct' must be imported}} - // expected-note@Inputs/module_private_left.h:3 {{previous definition is here}} - + HiddenStruct hidden; // expected-error{{unknown type name 'HiddenStruct'}} Integer i; // expected-error{{unknown type name 'Integer'}} int *ip = 0; diff --git a/clang/test/Modules/no-linkage.cpp b/clang/test/Modules/no-linkage.cpp new file mode 100644 index 00000000000..508464e8dbe --- /dev/null +++ b/clang/test/Modules/no-linkage.cpp @@ -0,0 +1,35 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodules-local-submodule-visibility -I%S/Inputs/no-linkage -fmodule-map-file=%S/Inputs/no-linkage/module.modulemap %s -verify + +#include "empty.h" + +namespace NS { int n; } // expected-note {{candidate}} +struct Typedef { int n; }; // expected-note {{candidate}} +int AliasDecl; // expected-note {{candidate}} +enum AlsoAnEnum { Enumerator }; // expected-note {{candidate}} +int UsingDecl; // expected-note {{candidate}} + +// expected-note@decls.h:2 {{candidate}} +// expected-note@decls.h:3 {{candidate}} +// expected-note@decls.h:4 {{candidate}} +// expected-note@decls.h:5 {{candidate}} +// expected-note@decls.h:6 {{candidate}} + +void use(int); +void use_things() { + use(Typedef().n); + use(NS::n); + use(AliasDecl); + use(Enumerator); + use(UsingDecl); +} + +#include "decls.h" + +void use_things_again() { + use(Typedef().n); // expected-error {{ambiguous}} + use(NS::n); // expected-error {{ambiguous}} expected-error{{'NS' is not a class, namespace, or enumeration}} + use(AliasDecl); // expected-error {{ambiguous}} + use(Enumerator); // expected-error {{ambiguous}} + use(UsingDecl); // expected-error {{ambiguous}} +} diff --git a/clang/test/Modules/submodule-visibility-cycles.cpp b/clang/test/Modules/submodule-visibility-cycles.cpp index f26f6f21eea..a01fe562b14 100644 --- a/clang/test/Modules/submodule-visibility-cycles.cpp +++ b/clang/test/Modules/submodule-visibility-cycles.cpp @@ -3,7 +3,7 @@ #include "cycle1.h" C1 c1; -C2 c2; // expected-error {{must be imported}} expected-error {{}} +C2 c2; // expected-error {{must be imported}} // expected-note@cycle2.h:6 {{here}} #include "cycle2.h" diff --git a/clang/test/Modules/submodules-merge-defs.cpp b/clang/test/Modules/submodules-merge-defs.cpp index bb8e69367ca..361f05b553e 100644 --- a/clang/test/Modules/submodules-merge-defs.cpp +++ b/clang/test/Modules/submodules-merge-defs.cpp @@ -12,7 +12,7 @@ #include "indirect.h" #endif -A pre_a; // expected-error {{must use 'struct'}} +A pre_a; #ifdef IMPORT_USE_2 // expected-error-re@-2 {{must be imported from one of {{.*}}stuff.use{{.*}}stuff.use-2}} #elif EARLY_INDIRECT_INCLUDE @@ -21,29 +21,28 @@ A pre_a; // expected-error {{must use 'struct'}} // expected-error@-6 {{must be imported from module 'stuff.use'}} #endif // expected-note@defs.h:1 +{{here}} +extern class A pre_a2; +int pre_use_a = use_a(pre_a2); // expected-error {{'A' must be imported}} expected-error {{'use_a' must be imported}} // expected-note@defs.h:2 +{{here}} -int pre_use_a = use_a(pre_a); // expected-error {{'A' must be imported}} expected-error {{'use_a' must be imported}} B::Inner2 pre_bi; // expected-error +{{must be imported}} // expected-note@defs.h:4 +{{here}} // expected-note@defs.h:17 +{{here}} -void pre_bfi(B b) { // expected-error {{must use 'class'}} expected-error +{{must be imported}} - b.f<int>(); // expected-error +{{must be imported}} expected-error +{{}} - // expected-note@defs.h:19 +{{here}} +void pre_bfi(B b) { // expected-error +{{must be imported}} + b.f<int>(); // expected-error +{{}} } C_Base<1> pre_cb1; // expected-error +{{must be imported}} // expected-note@defs.h:23 +{{here}} -C1 pre_c1; // expected-error +{{must be imported}} expected-error {{must use 'struct'}} +C1 pre_c1; // expected-error +{{must be imported}} // expected-note@defs.h:25 +{{here}} -C2 pre_c2; // expected-error +{{must be imported}} expected-error {{must use 'struct'}} +C2 pre_c2; // expected-error +{{must be imported}} // expected-note@defs.h:26 +{{here}} D::X pre_dx; // expected-error +{{must be imported}} // expected-note@defs.h:28 +{{here}} // expected-note@defs.h:29 +{{here}} -// FIXME: We should warn that use_dx is being used without being imported. -int pre_use_dx = use_dx(pre_dx); +int pre_use_dx = use_dx(pre_dx); // ignored; pre_dx is invalid int pre_e = E(0); // expected-error {{must be imported}} // expected-note@defs.h:32 +{{here}} @@ -69,8 +68,9 @@ J<> pre_j; // expected-error {{declaration of 'J' must be imported}} #endif // expected-note@defs.h:58 +{{here}} -ScopedEnum pre_scopedenum; // expected-error {{must be imported}} expected-error {{must use 'enum'}} -// expected-note@defs.h:106 {{here}} +ScopedEnum pre_scopedenum; // expected-error {{must be imported}} +// expected-note@defs.h:105 0-1{{here}} +// expected-note@defs.h:106 0-1{{here}} enum ScopedEnum : int; ScopedEnum pre_scopedenum_declared; // ok |

