summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-06-22 21:15:01 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-06-22 21:15:01 +0000
commit529ecb237ac423b29a555b5ef930c118d117a542 (patch)
tree5c849f3ce3528f70221036e39c8b3be19701bb8d
parent6072d2b97f7a4bf896d5fd308c5c07e33788f445 (diff)
downloadbcm5719-llvm-529ecb237ac423b29a555b5ef930c118d117a542.tar.gz
bcm5719-llvm-529ecb237ac423b29a555b5ef930c118d117a542.zip
[modules] Add a flag to disable the feature that permits conflicting redefinitions of internal-linkage symbols that are not visible.
Such conflicts are an accident waiting to happen, and this feature conflicts with the desire to include existing headers into multiple modules and merge the results. (In an ideal world, it should not be possible to export internal linkage symbols from a module, but sadly the glibc and libstdc++ headers provide 'static inline' functions in a few cases.) llvm-svn: 240335
-rw-r--r--clang/include/clang/Basic/LangOptions.def1
-rw-r--r--clang/include/clang/Driver/CC1Options.td4
-rw-r--r--clang/include/clang/Sema/Sema.h4
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp2
-rw-r--r--clang/lib/Sema/SemaDecl.cpp14
-rw-r--r--clang/test/Modules/submodules-merge-defs.cpp7
6 files changed, 25 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index bef122f093c..b27605b15d2 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -130,6 +130,7 @@ COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module us
BENIGN_LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery")
BENIGN_LANGOPT(ImplicitModules, 1, 1, "build modules that are not specified via -fmodule-file")
COMPATIBLE_LANGOPT(ModulesLocalVisibility, 1, 0, "local submodule visibility")
+COMPATIBLE_LANGOPT(ModulesHideInternalLinkage, 1, 1, "hiding non-visible internal linkage declarations from redeclaration lookup")
COMPATIBLE_LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro")
COMPATIBLE_LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")
diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td
index f2ef71e2f91..60cc6ec1156 100644
--- a/clang/include/clang/Driver/CC1Options.td
+++ b/clang/include/clang/Driver/CC1Options.td
@@ -369,6 +369,10 @@ def fmodules_local_submodule_visibility :
Flag<["-"], "fmodules-local-submodule-visibility">,
HelpText<"Enforce name visibility rules across submodules of the same "
"top-level module.">;
+def fno_modules_hide_internal_linkage :
+ Flag<["-"], "fno-modules-hide-internal-linkage">,
+ HelpText<"Make all declarations visible to redeclaration lookup, "
+ "even if they have internal linkage.">;
def fconcepts_ts : Flag<["-"], "fconcepts-ts">,
HelpText<"Enable C++ Extensions for Concepts.">;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 4d815262592..df5182b52f4 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -277,7 +277,9 @@ class Sema {
// it will keep having external linkage. If it has internal linkage, we
// will not link it. Since it has no previous decls, it will remain
// with internal linkage.
- return isVisible(Old) || New->isExternallyVisible();
+ if (getLangOpts().ModulesHideInternalLinkage)
+ return isVisible(Old) || New->isExternallyVisible();
+ return true;
}
public:
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 7a3391685a4..2d26548db39 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1521,6 +1521,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse;
Opts.ModulesLocalVisibility =
Args.hasArg(OPT_fmodules_local_submodule_visibility);
+ Opts.ModulesHideInternalLinkage =
+ !Args.hasArg(OPT_fno_modules_hide_internal_linkage);
Opts.ModulesSearchAll = Opts.Modules &&
!Args.hasArg(OPT_fno_modules_search_all) &&
Args.hasArg(OPT_fmodules_search_all);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index cb1be8d5053..ee039940585 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1804,7 +1804,8 @@ static void filterNonConflictingPreviousDecls(Sema &S,
NamedDecl *decl,
LookupResult &previous){
// This is only interesting when modules are enabled.
- if (!S.getLangOpts().Modules && !S.getLangOpts().ModulesLocalVisibility)
+ if ((!S.getLangOpts().Modules && !S.getLangOpts().ModulesLocalVisibility) ||
+ !S.getLangOpts().ModulesHideInternalLinkage)
return;
// Empty sets are uninteresting.
@@ -3453,8 +3454,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->isThisDeclarationADefinition() == VarDecl::Definition &&
(Def = Old->getDefinition())) {
NamedDecl *Hidden = nullptr;
- if (!hasVisibleDefinition(Def, &Hidden) &&
- (New->getDescribedVarTemplate() ||
+ if (!hasVisibleDefinition(Def, &Hidden) &&
+ (New->getFormalLinkage() == InternalLinkage ||
+ New->getDescribedVarTemplate() ||
New->getNumTemplateParameterLists() ||
New->getDeclContext()->isDependentContext())) {
// The previous definition is hidden, and multiple definitions are
@@ -8946,7 +8948,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if ((Def = VDecl->getDefinition()) && Def != VDecl) {
NamedDecl *Hidden = nullptr;
if (!hasVisibleDefinition(Def, &Hidden) &&
- (VDecl->getDescribedVarTemplate() ||
+ (VDecl->getFormalLinkage() == InternalLinkage ||
+ VDecl->getDescribedVarTemplate() ||
VDecl->getNumTemplateParameterLists() ||
VDecl->getDeclContext()->isDependentContext())) {
// The previous definition is hidden, and multiple definitions are
@@ -10367,7 +10370,8 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
// 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() ||
+ (Definition->getFormalLinkage() == InternalLinkage ||
+ Definition->isInlineSpecified() ||
Definition->getDescribedFunctionTemplate() ||
Definition->getNumTemplateParameterLists()))
return;
diff --git a/clang/test/Modules/submodules-merge-defs.cpp b/clang/test/Modules/submodules-merge-defs.cpp
index 94c0fd354c9..6f2754be462 100644
--- a/clang/test/Modules/submodules-merge-defs.cpp
+++ b/clang/test/Modules/submodules-merge-defs.cpp
@@ -3,7 +3,7 @@
// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/submodules-merge-defs %s -verify -fno-modules-error-recovery
// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/submodules-merge-defs %s -verify -fno-modules-error-recovery -fmodules-local-submodule-visibility -DTEXTUAL
// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/submodules-merge-defs %s -verify -fno-modules-error-recovery -fmodules-local-submodule-visibility
-// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules-cache-path=%t -fimplicit-module-maps -I %S/Inputs/submodules-merge-defs %s -verify -fno-modules-error-recovery -fmodules-local-submodule-visibility -DTEXTUAL -DEARLY_INDIRECT_INCLUDE
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules-cache-path=%t -fimplicit-module-maps -I %S/Inputs/submodules-merge-defs %s -verify -fno-modules-error-recovery -fmodules-local-submodule-visibility -DTEXTUAL -DEARLY_INDIRECT_INCLUDE -fno-modules-hide-internal-linkage
// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/submodules-merge-defs %s -verify -fno-modules-error-recovery -fmodules-local-submodule-visibility -fmodule-feature use_defs_twice -DIMPORT_USE_2
// Trigger import of definitions, but don't make them visible.
@@ -92,3 +92,8 @@ template<typename T, int N, template<typename> class K> struct J;
J<> post_j2;
FriendDefArg::Y<int> friend_def_arg;
FriendDefArg::D<> friend_def_arg_d;
+
+#ifdef TEXTUAL
+#include "use-defs.h"
+void use_static_inline() { StaticInline::g({}); }
+#endif
OpenPOWER on IntegriCloud