aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2013-02-19 01:57:35 +0000
committerJohn McCall <rjmccall@apple.com>2013-02-19 01:57:35 +0000
commita880b19aa6ef1dc95936f5de052be7a7d6ee6814 (patch)
tree5bfc6bbc9923a73e72a917920105bf1fb1f91df1 /lib
parent0b5a483c8f5d8563ebc6ad5e311f2fadb734058d (diff)
Add support for -fvisibility-ms-compat.
We treat this as an alternative to -fvisibility=<?> which changes the default value visibility to "hidden" and the default type visibility to "default". Expose a -cc1 option for changing the default type visibility, repurposing -fvisibility as the default value visibility option (also setting type visibility from it in the absence of a specific option). rdar://13079314 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175480 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/Decl.cpp17
-rw-r--r--lib/Driver/Tools.cpp16
-rw-r--r--lib/Frontend/CompilerInvocation.cpp42
3 files changed, 56 insertions, 19 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 0183c0b59e..6e93dd6415 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -80,7 +80,9 @@ typedef NamedDecl::LinkageInfo LinkageInfo;
/// Is the given declaration a "type" or a "value" for the purposes of
/// visibility computation?
static bool usesTypeVisibility(const NamedDecl *D) {
- return isa<TypeDecl>(D) || isa<ClassTemplateDecl>(D);
+ return isa<TypeDecl>(D) ||
+ isa<ClassTemplateDecl>(D) ||
+ isa<ObjCInterfaceDecl>(D);
}
/// Return the explicit visibility of the given declaration.
@@ -440,10 +442,15 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// Add in global settings if the above didn't give us direct visibility.
if (!LV.visibilityExplicit()) {
- // FIXME: type visibility
- LV.mergeVisibility(Context.getLangOpts().getVisibilityMode(),
- /*explicit*/ false);
-
+ // Use global type/value visibility as appropriate.
+ Visibility globalVisibility;
+ if (computation == LVForValue) {
+ globalVisibility = Context.getLangOpts().getValueVisibilityMode();
+ } else {
+ assert(computation == LVForType);
+ globalVisibility = Context.getLangOpts().getTypeVisibilityMode();
+ }
+ LV.mergeVisibility(globalVisibility, /*explicit*/ false);
// If we're paying attention to global visibility, apply
// -finline-visibility-hidden if this is an inline method.
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index f5ea38bec4..5b3b65428d 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -2523,9 +2523,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(Twine(N)));
}
- if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ)) {
- CmdArgs.push_back("-fvisibility");
- CmdArgs.push_back(A->getValue());
+ // -fvisibility= and -fvisibility-ms-compat are of a piece.
+ if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ,
+ options::OPT_fvisibility_ms_compat)) {
+ if (A->getOption().matches(options::OPT_fvisibility_EQ)) {
+ CmdArgs.push_back("-fvisibility");
+ CmdArgs.push_back(A->getValue());
+ } else {
+ assert(A->getOption().matches(options::OPT_fvisibility_ms_compat));
+ CmdArgs.push_back("-fvisibility");
+ CmdArgs.push_back("hidden");
+ CmdArgs.push_back("-ftype-visibility");
+ CmdArgs.push_back("default");
+ }
}
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index f4bf4b7756..05e079470a 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1001,6 +1001,24 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.DollarIdents = !Opts.AsmPreprocessor;
}
+/// Attempt to parse a visibility value out of the given argument.
+static Visibility parseVisibility(Arg *arg, ArgList &args,
+ DiagnosticsEngine &diags) {
+ StringRef value = arg->getValue();
+ if (value == "default") {
+ return DefaultVisibility;
+ } else if (value == "hidden") {
+ return HiddenVisibility;
+ } else if (value == "protected") {
+ // FIXME: diagnose if target does not support protected visibility
+ return ProtectedVisibility;
+ }
+
+ diags.Report(diag::err_drv_invalid_value)
+ << arg->getAsString(args) << value;
+ return DefaultVisibility;
+}
+
static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags) {
// FIXME: Cleanup per-file based stuff.
@@ -1132,17 +1150,19 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_fdelayed_template_parsing))
Opts.DelayedTemplateParsing = 1;
- StringRef Vis = Args.getLastArgValue(OPT_fvisibility, "default");
- if (Vis == "default")
- Opts.setVisibilityMode(DefaultVisibility);
- else if (Vis == "hidden")
- Opts.setVisibilityMode(HiddenVisibility);
- else if (Vis == "protected")
- // FIXME: diagnose if target does not support protected visibility
- Opts.setVisibilityMode(ProtectedVisibility);
- else
- Diags.Report(diag::err_drv_invalid_value)
- << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis;
+ // The value-visibility mode defaults to "default".
+ if (Arg *visOpt = Args.getLastArg(OPT_fvisibility)) {
+ Opts.setValueVisibilityMode(parseVisibility(visOpt, Args, Diags));
+ } else {
+ Opts.setValueVisibilityMode(DefaultVisibility);
+ }
+
+ // The type-visibility mode defaults to the value-visibility mode.
+ if (Arg *typeVisOpt = Args.getLastArg(OPT_ftype_visibility)) {
+ Opts.setTypeVisibilityMode(parseVisibility(typeVisOpt, Args, Diags));
+ } else {
+ Opts.setTypeVisibilityMode(Opts.getValueVisibilityMode());
+ }
if (Args.hasArg(OPT_fvisibility_inlines_hidden))
Opts.InlineVisibilityHidden = 1;