From: Richard Smith Date: Fri, 27 Mar 2015 20:16:58 +0000 (+0000) Subject: [modules] Allow a function to be redefined if the old definition is not visible. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d4edf611010ebb5d7fa0c0e7a699831ac9ea3766;p=clang [modules] Allow a function to be redefined if the old definition is not visible. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@233407 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 88217b9283..7078cd8cdc 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1282,6 +1282,10 @@ public: /// Determine if \p D has a visible definition. If not, suggest a declaration /// that should be made visible to expose the definition. bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested); + bool hasVisibleDefinition(const NamedDecl *D) { + NamedDecl *Hidden; + return hasVisibleDefinition(const_cast(D), &Hidden); + } bool RequireCompleteType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9bbfeaf19e..3b9bb842c4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -10282,6 +10282,15 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, if (canRedefineFunction(Definition, getLangOpts())) return; + // If we don't have a visible definition of the function, and it's inline, + // it's OK to form another definition of it. + // + // FIXME: Should we skip the body of the function and use the old definition + // in this case? That may be necessary for functions that return local types + // through a deduced return type, or instantiate templates with local types. + if (!hasVisibleDefinition(Definition) && Definition->isInlineSpecified()) + return; + if (getLangOpts().GNUMode && Definition->isInlineSpecified() && Definition->getStorageClass() == SC_Extern) Diag(FD->getLocation(), diag::err_redefinition_extern_inline) diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index ac7376efbc..1244829f2b 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1226,8 +1226,7 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { DeclContext *DC = D->getLexicalDeclContext(); if (!D->isModulePrivate() && DC && !DC->isFileContext() && !isa(DC)) { - NamedDecl *Hidden; - if (SemaRef.hasVisibleDefinition(cast(DC), &Hidden)) { + if (SemaRef.hasVisibleDefinition(cast(DC))) { if (SemaRef.ActiveTemplateInstantiations.empty()) { // Cache the fact that this declaration is implicitly visible because // its parent has a visible definition. diff --git a/test/Modules/Inputs/submodules-merge-defs/defs.h b/test/Modules/Inputs/submodules-merge-defs/defs.h index 16f71840d0..3a9c2327c7 100644 --- a/test/Modules/Inputs/submodules-merge-defs/defs.h +++ b/test/Modules/Inputs/submodules-merge-defs/defs.h @@ -1,5 +1,5 @@ struct A { int a_member; }; -namespace { inline int use_a(A a) { return a.a_member; } } +inline int use_a(A a) { return a.a_member; } class B { struct Inner1 {}; @@ -17,4 +17,4 @@ struct C2 : C_Base::D{} extern c2; typedef struct { int a; void f(); struct X; } D; struct D::X { int dx; } extern dx; -namespace { inline int use_dx(D::X dx) { return dx.dx; } } +inline int use_dx(D::X dx) { return dx.dx; } diff --git a/test/Modules/submodules-merge-defs.cpp b/test/Modules/submodules-merge-defs.cpp index cdda48ea65..86e50368a9 100644 --- a/test/Modules/submodules-merge-defs.cpp +++ b/test/Modules/submodules-merge-defs.cpp @@ -5,7 +5,9 @@ #include "empty.h" A pre_a; // expected-error {{must be imported}} expected-error {{must use 'struct'}} -// expected-note@defs.h:1 {{here}} +// expected-note@defs.h:1 +{{here}} +// FIXME: We should warn that use_a is being used without being imported. +int pre_use_a = use_a(pre_a); // expected-error {{'A' must be imported}} B::Inner2 pre_bi; // expected-error +{{must be imported}} // expected-note@defs.h:4 +{{here}} @@ -21,13 +23,17 @@ C2 pre_c2; // expected-error +{{must be imported}} expected-error {{must use 'st D::X pre_dx; // expected-error +{{must be imported}} // expected-note@defs.h:18 +{{here}} // expected-note@defs.h:19 +{{here}} +// FIXME: We should warn that use_dx is being used without being imported. +int pre_use_dx = use_dx(pre_dx); // Make definitions from second module visible. #include "import-and-redefine.h" A post_a; +int post_use_a = use_a(post_a); B::Inner2 post_bi; C_Base<1> post_cb1; C1 c1; C2 c2; D::X post_dx; +int post_use_dx = use_dx(post_dx);