diff options
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 3 | ||||
| -rw-r--r-- | clang/test/Modules/Inputs/submodules-merge-defs/defs.h | 4 | ||||
| -rw-r--r-- | clang/test/Modules/submodules-merge-defs.cpp | 8 |
5 files changed, 23 insertions, 5 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 88217b9283d..7078cd8cdca 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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<NamedDecl*>(D), &Hidden); + } bool RequireCompleteType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9bbfeaf19ef..3b9bb842c4e 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index ac7376efbc4..1244829f2ba 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/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<LinkageSpecDecl>(DC)) { - NamedDecl *Hidden; - if (SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC), &Hidden)) { + if (SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC))) { if (SemaRef.ActiveTemplateInstantiations.empty()) { // Cache the fact that this declaration is implicitly visible because // its parent has a visible definition. diff --git a/clang/test/Modules/Inputs/submodules-merge-defs/defs.h b/clang/test/Modules/Inputs/submodules-merge-defs/defs.h index 16f71840d0a..3a9c2327c7a 100644 --- a/clang/test/Modules/Inputs/submodules-merge-defs/defs.h +++ b/clang/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<C_Const<0>::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/clang/test/Modules/submodules-merge-defs.cpp b/clang/test/Modules/submodules-merge-defs.cpp index cdda48ea652..86e50368a9e 100644 --- a/clang/test/Modules/submodules-merge-defs.cpp +++ b/clang/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); |

