aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-04-11 15:29:25 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-04-11 15:29:25 +0200
commitcb8ac8e4b8c1fd9684f43fa5916f73d494ed817f (patch)
treebb0c26250e5fe886b3fdd29ae98978b67540fc78
parented024f5c4e42bf1bc32d5721c83b990987b3aa74 (diff)
Default to strict mode (/permissive-) from VC15.5
-rw-r--r--build2/cc/compile-rule.cxx2
-rw-r--r--build2/cxx/init.cxx376
-rw-r--r--build2/target.hxx2
3 files changed, 191 insertions, 189 deletions
diff --git a/build2/cc/compile-rule.cxx b/build2/cc/compile-rule.cxx
index 9e307b6..3ed6075 100644
--- a/build2/cc/compile-rule.cxx
+++ b/build2/cc/compile-rule.cxx
@@ -3183,7 +3183,7 @@ namespace build2
if (ps)
psrc.active = true; // Re-arm.
- // Prior to 15u5 (19.12) VC was not using the 'export module M;'
+ // Prior to 15.5 (19.12) VC was not using the 'export module M;'
// syntax so we use the preprequisite type to distinguish between
// interface and implementation units.
//
diff --git a/build2/cxx/init.cxx b/build2/cxx/init.cxx
index 7174121..d32012c 100644
--- a/build2/cxx/init.cxx
+++ b/build2/cxx/init.cxx
@@ -73,245 +73,247 @@ namespace build2
bool modules (false); auto& v_m (enter ("cxx.features.modules"));
// Translate "latest" and "experimental" to the compiler/version-
- // appropriate option(s).
+ // appropriate option(s). Experimental is normally like latest with
+ // extra stuff enabled via additional flags. Otherwise translate the
+ // standard value.
//
- if (v != nullptr && (*v == "latest" || *v == "experimental"))
- {
- // Experimental is like latest with some extra stuff enabled via
- // additional switches.
- //
- const char* o (nullptr);
+ bool experimental ( v != nullptr && *v == "experimental");
+ bool latest (experimental || (v != nullptr && *v == "latest"));
+
+ string o;
- switch (ct)
+ switch (cl)
+ {
+ case compiler_class::msvc:
{
- case compiler_type::msvc:
+ // C++ standard-wise, with VC you got what you got up until 14.2.
+ // Starting with 14.3 there is now the /std: switch which defaults
+ // to c++14 but can be set to c++latest. And from 15.3 it can be
+ // c++17.
+ //
+ // The question is also whether we should verify that the requested
+ // standard is provided by this VC version. And if so, from which
+ // version should we say VC supports 11, 14, and 17? We should
+ // probably be as loose as possible here since the author will
+ // always be able to tighten (but not loosen) this in the buildfile
+ // (i.e., detect unsupported versions).
+ //
+ // For now we are not going to bother doing this for C++03.
+ //
+ if (latest)
{
- // VC14u3 and later has /std:c++latest.
- //
if (mj > 19 || (mj == 19 && (mi > 0 || (mi == 0 && p >= 24215))))
o = "/std:c++latest";
-
- break;
}
- case compiler_type::gcc:
+ else if (v == nullptr)
+ ;
+ else if (*v != "98" && *v != "03")
{
- if (mj >= 8) o = "-std=c++2a"; // 20
- else if (mj >= 5) o = "-std=c++1z"; // 17
- else if (mj == 4 && mi >= 8) o = "-std=c++1y"; // 14
- else if (mj == 4 && mi >= 4) o = "-std=c++0x"; // 11
+ bool sup (false);
- break;
- }
- case compiler_type::clang:
- {
- // Remap Apple versions to vanilla Clang based on the following
- // release point. Note that Apple no longer discloses the mapping
- // so it's a guesswork and we try to be conservative. For details
- // see:
- //
- // https://gist.github.com/yamaya/2924292
- //
- // 5.1 -> 3.4
- // 6.0 -> 3.5
- // 7.0 -> 3.7
- // 7.3 -> 3.8
- // 8.0 -> 3.9
- // 9.0 -> 4.0 (later ones could be 5.0)
- // 9.1 -> ?
- // 10.0 -> ?
- //
- // Note that this mapping is also used to enable experimental
- // features below.
- //
- if (ci.id.variant == "apple")
+ if (*v == "11") // C++11 since VS2010/10.0.
+ {
+ sup = mj >= 16;
+ }
+ else if (*v == "14") // C++14 since VS2015/14.0.
+ {
+ sup = mj >= 19;
+ }
+ else if (*v == "17") // C++17 since VS2015/14.0u2.
{
- if (mj >= 9) {mj = 4; mi = 0;}
- else if (mj == 8) {mj = 3; mi = 9;}
- else if (mj == 7 && mi >= 3) {mj = 3; mi = 8;}
- else if (mj == 7) {mj = 3; mi = 7;}
- else if (mj == 6) {mj = 3; mi = 5;}
- else if (mj == 5 && mi >= 1) {mj = 3; mi = 4;}
- else {mj = 3; mi = 0;}
+ // Note: the VC15 compiler version is 19.10.
+ //
+ sup = (mj > 19 ||
+ (mj == 19 && (mi > 0 || (mi == 0 && p >= 23918))));
}
- if (mj >= 5) o = "-std=c++2a"; // 20
- else if (mj > 3 || (mj == 3 && mi >= 5)) o = "-std=c++1z"; // 17
- else if (mj == 3 && mi >= 4) o = "-std=c++1y"; // 14
- else /* ??? */ o = "-std=c++0x"; // 11
+ if (!sup)
+ fail << "C++" << *v << " is not supported by " << ci.signature <<
+ info << "required by " << project (rs) << '@' << rs.out_path ();
- break;
+ if (mj > 19 || (mj == 19 && mi >= 11)) // 15.3
+ {
+ if (*v == "14") o = "/std:c++14";
+ else if (*v == "17") o = "/std:c++17";
+ }
+ else if (mj == 19 && (mi > 0 || (mi == 0 && p >= 24215))) // 14.3
+ {
+ if (*v == "14") o = "/std:c++14";
+ else if (*v == "17") o = "/std:c++latest";
+ }
}
- case compiler_type::icc:
- {
- if (mj >= 17) o = "-std=c++1z"; // 17
- else if (mj > 15 || (mj == 15 && p >= 3)) o = "-std=c++1y"; // 14
- else /* ??? */ o = "-std=c++0x"; // 11
- break;
- }
- }
+ if (!o.empty ())
+ r.push_back (move (o));
- if (o != nullptr)
- r.push_back (o);
+ // Starting with 15.5 (19.12) Visual Studio-created projects default
+ // to the strict mode.
+ //
+ if (mj > 19 || (mj == 19 && mi >= 12))
+ r.push_back ("/permissive-");
- if (*v == "experimental")
+ break;
+ }
+ case compiler_class::gcc:
{
- // Unless disabled by the user, try to enable C++ modules. Here
- // we use a tri-state:
- //
- // - false - disabled
- // - unspecified - enabled if practically usable
- // - true - enabled even if practically unusable
- //
- lookup l;
- if (!(l = rs[v_m]) || cast<bool> (l))
+ if (latest)
{
switch (ct)
{
- case compiler_type::msvc:
- {
- // While modules are supported in VC15u0 (19.10), there is a
- // bug in separate interface/implementation unit support which
- // makes them pretty much unusable. This has been fixed in
- // VC15u3 (19.11). And VC15u5 (19.12) supports the 'export
- // module M;' syntax.
- //
- if (mj > 19 || (mj == 19 && mi >= (l ? 10 : 12)))
- {
- r.push_back (
- mj > 19 || mi > 11
- ? "/D__cpp_modules=201704" // p0629r0 (export module M;)
- : "/D__cpp_modules=201703"); // n4647 ( module M;)
-
- r.push_back ("/experimental:module");
- modules = true;
- }
- break;
- }
case compiler_type::gcc:
{
- // Enable starting with GCC 9.0.0 (currently the c++-modules
- // branch).
- //
- if (mj >= 9 &&
- ci.version.build.find ("c++-modules") != string::npos)
- {
- // Currently defines __cpp_modules=201810 which is said to
- // correspond to p1103 (merged modules).
- //
- r.push_back ("-fmodules-ts");
- modules = true;
- }
+ if (mj >= 8) o = "-std=c++2a"; // 20
+ else if (mj >= 5) o = "-std=c++1z"; // 17
+ else if (mj == 4 && mi >= 8) o = "-std=c++1y"; // 14
+ else if (mj == 4 && mi >= 4) o = "-std=c++0x"; // 11
+
break;
}
case compiler_type::clang:
{
- // Enable starting with Clang 6.0.0.
+ // Remap Apple versions to vanilla Clang based on the
+ // following release point. Note that Apple no longer
+ // discloses the mapping so it's a guesswork and we try to be
+ // conservative. For details see:
//
- // Note that we are using Apple to vanilla Clang version re-
- // map from above so may need to update things there as well.
+ // https://gist.github.com/yamaya/2924292
//
- // Also see Clang modules support hack in cc::compile.
+ // 5.1 -> 3.4
+ // 6.0 -> 3.5
+ // 7.0 -> 3.7
+ // 7.3 -> 3.8
+ // 8.0 -> 3.9
+ // 9.0 -> 4.0 (later ones could be 5.0)
+ // 9.1 -> ?
+ // 10.0 -> ?
//
- if (mj >= 6)
+ // Note that this mapping is also used to enable experimental
+ // features below.
+ //
+ if (ci.id.variant == "apple")
{
- r.push_back ("-D__cpp_modules=201704"); // p0629r0
- r.push_back ("-fmodules-ts");
- modules = true;
+ if (mj >= 9) {mj = 4; mi = 0;}
+ else if (mj == 8) {mj = 3; mi = 9;}
+ else if (mj == 7 && mi >= 3) {mj = 3; mi = 8;}
+ else if (mj == 7) {mj = 3; mi = 7;}
+ else if (mj == 6) {mj = 3; mi = 5;}
+ else if (mj == 5 && mi >= 1) {mj = 3; mi = 4;}
+ else {mj = 3; mi = 0;}
}
+
+ if (mj >= 5) o = "-std=c++2a";
+ else if (mj > 3 || (mj == 3 && mi >= 5)) o = "-std=c++1z";
+ else if (mj == 3 && mi >= 4) o = "-std=c++1y";
+ else /* ??? */ o = "-std=c++0x";
+
break;
}
case compiler_type::icc:
- break; // No modules support yet.
+ {
+ if (mj >= 17) o = "-std=c++1z";
+ else if (mj > 15 || (mj == 15 && p >= 3)) o = "-std=c++1y";
+ else /* ??? */ o = "-std=c++0x";
+
+ break;
+ }
+ default:
+ assert (false);
}
}
+ else if (v == nullptr)
+ ;
+ else
+ {
+ // Translate 11 to 0x, 14 to 1y, 17 to 1z, and 20 to 2a for
+ // compatibility with older versions of the compilers.
+ //
+ o = "-std=";
+
+ if (*v == "98") o += "c++98";
+ else if (*v == "03") o += "c++03";
+ else if (*v == "11") o += "c++0x";
+ else if (*v == "14") o += "c++1y";
+ else if (*v == "17") o += "c++1z";
+ else if (*v == "20") o += "c++2a";
+ else o += *v; // In case the user specifies e.g., 'gnu++17'.
+ }
+
+ if (!o.empty ())
+ r.push_back (move (o));
+
+ break;
}
}
- else
+
+ if (experimental)
{
- // Otherwise translate the standard value.
+ // Unless disabled by the user, try to enable C++ modules. Here we use
+ // a tri-state:
//
- switch (cl)
+ // - false - disabled
+ // - unspecified - enabled if practically usable
+ // - true - enabled even if practically unusable
+ //
+ lookup l;
+ if (!(l = rs[v_m]) || cast<bool> (l))
{
- case compiler_class::msvc:
+ switch (ct)
{
- // C++ standard-wise, with VC you got what you got up until 14u2.
- // Starting with 14u3 there is now the /std: switch which defaults
- // to c++14 but can be set to c++latest. And from 15u3 it can be
- // c++17.
- //
- // The question is also whether we should verify that the
- // requested standard is provided by this VC version. And if so,
- // from which version should we say VC supports 11, 14, and 17? We
- // should probably be as loose as possible here since the author
- // will always be able to tighten (but not loosen) this in the
- // buildfile (i.e., detect unsupported versions).
- //
- // For now we are not going to bother doing this for C++03.
- //
- if (v == nullptr)
- ;
- else if (*v != "98" && *v != "03")
+ case compiler_type::msvc:
{
- bool sup (false);
-
- if (*v == "11") // C++11 since VS2010/10.0.
+ // While modules are supported in VC15.0 (19.10), there is a bug
+ // in separate interface/implementation unit support which makes
+ // them pretty much unusable. This has been fixed in VC15.3
+ // (19.11). And VC15.5 (19.12) supports the 'export module M;'
+ // syntax.
+ //
+ if (mj > 19 || (mj == 19 && mi >= (l ? 10 : 12)))
{
- sup = mj >= 16;
- }
- else if (*v == "14") // C++14 since VS2015/14.0.
- {
- sup = mj >= 19;
- }
- else if (*v == "17") // C++17 since VS2015/14.0u2.
- {
- // Note: the VC15 compiler version is 19.10.
- //
- sup = (mj > 19 ||
- (mj == 19 && (mi > 0 || (mi == 0 && p >= 23918))));
- }
-
- if (!sup)
- fail << "C++" << *v << " is not supported by "
- << ci.signature <<
- info << "required by " << project (rs) << '@'
- << rs.out_path ();
+ r.push_back (
+ mj > 19 || mi > 11
+ ? "/D__cpp_modules=201704" // p0629r0 (export module M;)
+ : "/D__cpp_modules=201703"); // n4647 ( module M;)
- if (mj > 19 || (mj == 19 && mi >= 11)) // 15u3
- {
- if (*v == "14") r.push_back ("/std:c++14");
- else if (*v == "17") r.push_back ("/std:c++17");
+ r.push_back ("/experimental:module");
+ modules = true;
}
- else if (mj == 19 && (mi > 0 || (mi == 0 && p >= 24215))) // 14u3
+ break;
+ }
+ case compiler_type::gcc:
+ {
+ // Enable starting with GCC 9.0.0 (currently the c++-modules
+ // branch).
+ //
+ if (mj >= 9 &&
+ ci.version.build.find ("c++-modules") != string::npos)
{
- if (*v == "14") r.push_back ("/std:c++14");
- else if (*v == "17") r.push_back ("/std:c++latest");
+ // Currently defines __cpp_modules=201810 which is said to
+ // correspond to p1103 (merged modules).
+ //
+ r.push_back ("-fmodules-ts");
+ modules = true;
}
+ break;
}
- break;
- }
- case compiler_class::gcc:
- {
- // Translate 11 to 0x, 14 to 1y, 17 to 1z, and 20 to 2a for
- // compatibility with older versions of the compilers.
- //
- if (v == nullptr)
- ;
- else
+ case compiler_type::clang:
{
- string o ("-std=");
-
- if (*v == "98") o += "c++98";
- else if (*v == "03") o += "c++03";
- else if (*v == "11") o += "c++0x";
- else if (*v == "14") o += "c++1y";
- else if (*v == "17") o += "c++1z";
- else if (*v == "20") o += "c++2a";
- else o += *v; // In case the user specifies e.g., 'gnu++17'.
-
- r.push_back (move (o));
+ // Enable starting with Clang 6.0.0.
+ //
+ // Note that we are using Apple to vanilla Clang version re-map
+ // from above so may need to update things there as well.
+ //
+ // Also see Clang modules support hack in cc::compile.
+ //
+ if (mj >= 6)
+ {
+ r.push_back ("-D__cpp_modules=201704"); // p0629r0
+ r.push_back ("-fmodules-ts");
+ modules = true;
+ }
+ break;
}
- break;
+ case compiler_type::icc:
+ break; // No modules support yet.
}
}
}
diff --git a/build2/target.hxx b/build2/target.hxx
index fafb689..cb1163f 100644
--- a/build2/target.hxx
+++ b/build2/target.hxx
@@ -51,7 +51,7 @@ namespace build2
//
// Note that max size for the "small capture optimization" in std::function
// ranges (in pointer sizes) from 0 (GCC prior to 5) to 2 (GCC 5) to 6 (VC
- // 14u2). With the size ranging (in bytes for 64-bit target) from 32 (GCC)
+ // 14.2). With the size ranging (in bytes for 64-bit target) from 32 (GCC)
// to 64 (VC).
//
using recipe_function = target_state (action, const target&);