Skip to content

Commit e503256

Browse files
committedOct 2, 2019
[ClangFormat] Future-proof Standard option, allow floating or pinning to arbitrary lang version
Summary: The historical context: - clang-format was written when C++11 was current, and the main language-version concern was >> vs > > template-closers. An option was added to allow selection of the 03/11 behavior, or auto-detection. - there was no option to choose simply "latest standard" so anyone who didn't ever want 03 behavior or auto-detection specified Cpp11. - In r185149 this option started to affect lexer mode. - no options were added to cover c++14, as parsing/formatting didn't change that much. The usage of Cpp11 to mean "latest" became codified e.g. in r206263 - c++17 added some new constructs. These were mostly backwards-compatible and so not used in old programs, so having no way to turn them off was OK. - c++20 added some new constructs and keywords (e.g. co_*) that changed the meaning of existing programs, and people started to complain that the c++20 parsing couldn't be turned off. New plan: - Default ('Auto') behavior remains unchanged: parse as latest, format template-closers based on input. - Add new 'Latest' option that more clearly expresses the intent "use modern features" that many projects have chosen for their .clang-format files. - Allow pinning to *any* language version, using the same name as clang -std: c++03, c++11, c++14 etc. These set precise lexer options, and any clang-format code depending on these can use a >= check. - For backwards compatibility, `Cpp11` is an alias for `Latest`, not `c++11`. This matches the historical documented semantics of this option. This spelling (and `Cpp03`) are deprecated. Reviewers: klimek, modocache Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D67541 llvm-svn: 373439
1 parent b54302e commit e503256

File tree

4 files changed

+92
-26
lines changed

4 files changed

+92
-26
lines changed
 

‎clang/docs/ClangFormatStyleOptions.rst

+22-6
Original file line numberDiff line numberDiff line change
@@ -2288,22 +2288,38 @@ the configuration (without a prefix: ``Auto``).
22882288
std::unique_ptr<int[]> foo() {} // Won't be affected
22892289

22902290
**Standard** (``LanguageStandard``)
2291-
Format compatible with this standard, e.g. use ``A<A<int> >``
2292-
instead of ``A<A<int>>`` for ``LS_Cpp03``.
2291+
.. code-block:: c++
2292+
2293+
c++03: latest:
2294+
vector<set<int> > x; vs. vector<set<int>> x;
2295+
Parse and format C++ constructs compatible with this standard.
22932296

22942297
Possible values:
22952298

2296-
* ``LS_Cpp03`` (in configuration: ``Cpp03``)
2299+
* ``LS_Cpp03`` (in configuration: ``c++03``)
22972300
Use C++03-compatible syntax.
22982301

2299-
* ``LS_Cpp11`` (in configuration: ``Cpp11``)
2300-
Use features of C++11, C++14 and C++1z (e.g. ``A<A<int>>`` instead of
2301-
``A<A<int> >``).
2302+
* ``LS_Cpp11`` (in configuration: ``c++11``)
2303+
Use C++11-compatible syntax.
2304+
2305+
* ``LS_Cpp14`` (in configuration: ``c++14``)
2306+
Use C++14-compatible syntax.
2307+
2308+
* ``LS_Cpp17`` (in configuration: ``c++17``)
2309+
Use C++17-compatible syntax.
2310+
2311+
* ``LS_Cpp20`` (in configuration: ``c++20``)
2312+
Use C++20-compatible syntax.
2313+
2314+
* ``LS_Latest`` (in configuration: ``Latest``)
2315+
Parse and format using the latest supported language version.
23022316

23032317
* ``LS_Auto`` (in configuration: ``Auto``)
23042318
Automatic detection based on the input.
23052319

2320+
* ``Cpp03``: deprecated alias for ``c++03``
23062321

2322+
* ``Cpp11``: deprecated alias for ``Latest``
23072323

23082324
**StatementMacros** (``std::vector<std::string>``)
23092325
A vector of macros that should be interpreted as complete

‎clang/include/clang/Format/Format.h

+23-6
Original file line numberDiff line numberDiff line change
@@ -1945,15 +1945,32 @@ struct FormatStyle {
19451945
/// \endcode
19461946
bool SpacesInSquareBrackets;
19471947

1948-
/// Supported language standards.
1948+
/// Supported language standards for parsing and formatting C++ constructs.
1949+
/// \code
1950+
/// Latest: vector<set<int>>
1951+
/// c++03 vs. vector<set<int> >
1952+
/// \endcode
1953+
///
1954+
/// The correct way to spell a specific language version is e.g. ``c++11``.
1955+
/// The historical aliases ``Cpp03`` and ``Cpp11`` are deprecated.
19491956
enum LanguageStandard {
1950-
/// Use C++03-compatible syntax.
1957+
/// c++03: Parse and format as C++03.
19511958
LS_Cpp03,
1952-
/// Use features of C++11, C++14 and C++1z (e.g. ``A<A<int>>`` instead of
1953-
/// ``A<A<int> >``).
1959+
/// c++11: Parse and format as C++11.
19541960
LS_Cpp11,
1955-
/// Automatic detection based on the input.
1956-
LS_Auto
1961+
/// c++14: Parse and format as C++14.
1962+
LS_Cpp14,
1963+
/// c++17: Parse and format as C++17.
1964+
LS_Cpp17,
1965+
/// c++20: Parse and format as C++20.
1966+
LS_Cpp20,
1967+
/// Latest: Parse and format using the latest supported language version.
1968+
/// 'Cpp11' is an alias for LS_Latest for historical reasons.
1969+
LS_Latest,
1970+
1971+
/// Auto: Automatic detection based on the input.
1972+
/// Parse using the latest language version. Format based on detected input.
1973+
LS_Auto,
19571974
};
19581975

19591976
/// Format compatible with this standard, e.g. use ``A<A<int> >``

‎clang/lib/Format/Format.cpp

+25-12
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,19 @@ template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
6767

6868
template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
6969
static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
70-
IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03);
71-
IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03);
72-
IO.enumCase(Value, "Cpp11", FormatStyle::LS_Cpp11);
73-
IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11);
70+
IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);
71+
IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias
72+
IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias
73+
74+
IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);
75+
IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias
76+
77+
IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);
78+
IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);
79+
IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);
80+
81+
IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);
82+
IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias
7483
IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
7584
}
7685
};
@@ -756,7 +765,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
756765
LLVMStyle.ObjCSpaceBeforeProtocolList = true;
757766
LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
758767
LLVMStyle.SpacesBeforeTrailingComments = 1;
759-
LLVMStyle.Standard = FormatStyle::LS_Cpp11;
768+
LLVMStyle.Standard = FormatStyle::LS_Latest;
760769
LLVMStyle.UseTab = FormatStyle::UT_Never;
761770
LLVMStyle.ReflowComments = true;
762771
LLVMStyle.SpacesInParentheses = false;
@@ -1399,7 +1408,7 @@ class Formatter : public TokenAnalyzer {
13991408
: FormatStyle::PAS_Right;
14001409
if (Style.Standard == FormatStyle::LS_Auto)
14011410
Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
1402-
? FormatStyle::LS_Cpp11
1411+
? FormatStyle::LS_Latest
14031412
: FormatStyle::LS_Cpp03;
14041413
BinPackInconclusiveFunctions =
14051414
HasBinPackedFunction || !HasOnePerLineFunction;
@@ -2455,14 +2464,18 @@ tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
24552464

24562465
LangOptions getFormattingLangOpts(const FormatStyle &Style) {
24572466
LangOptions LangOpts;
2458-
FormatStyle::LanguageStandard LexingStd =
2459-
Style.Standard == FormatStyle::LS_Auto ? FormatStyle::LS_Cpp11
2460-
: Style.Standard;
2467+
2468+
FormatStyle::LanguageStandard LexingStd = Style.Standard;
2469+
if (LexingStd == FormatStyle::LS_Auto)
2470+
LexingStd = FormatStyle::LS_Latest;
2471+
if (LexingStd == FormatStyle::LS_Latest)
2472+
LexingStd = FormatStyle::LS_Cpp20;
24612473
LangOpts.CPlusPlus = 1;
24622474
LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11;
2463-
LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp11;
2464-
LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp11;
2465-
LangOpts.CPlusPlus2a = LexingStd >= FormatStyle::LS_Cpp11;
2475+
LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;
2476+
LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
2477+
LangOpts.CPlusPlus2a = LexingStd >= FormatStyle::LS_Cpp20;
2478+
24662479
LangOpts.LineComment = 1;
24672480
bool AlternativeOperators = Style.isCpp();
24682481
LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;

‎clang/unittests/Format/FormatTest.cpp

+22-2
Original file line numberDiff line numberDiff line change
@@ -9388,6 +9388,19 @@ TEST_F(FormatTest, DoesNotTryToParseUDLiteralsInPreCpp11Code) {
93889388
format("#define x(_a) printf(\"foo\"_a);", Style));
93899389
}
93909390

9391+
TEST_F(FormatTest, CppLexVersion) {
9392+
FormatStyle Style = getLLVMStyle();
9393+
// Formatting of x * y differs if x is a type.
9394+
verifyFormat("void foo() { MACRO(a * b); }", Style);
9395+
verifyFormat("void foo() { MACRO(int *b); }", Style);
9396+
9397+
// LLVM style uses latest lexer.
9398+
verifyFormat("void foo() { MACRO(char8_t *b); }", Style);
9399+
Style.Standard = FormatStyle::LS_Cpp17;
9400+
// But in c++17, char8_t isn't a keyword.
9401+
verifyFormat("void foo() { MACRO(char8_t * b); }", Style);
9402+
}
9403+
93919404
TEST_F(FormatTest, UnderstandsCpp1y) { verifyFormat("int bi{1'000'000};"); }
93929405

93939406
TEST_F(FormatTest, BreakStringLiteralsBeforeUnbreakableTokenSequence) {
@@ -12305,11 +12318,18 @@ TEST_F(FormatTest, ParsesConfiguration) {
1230512318
FormatStyle::PAS_Middle);
1230612319

1230712320
Style.Standard = FormatStyle::LS_Auto;
12321+
CHECK_PARSE("Standard: c++03", Standard, FormatStyle::LS_Cpp03);
12322+
CHECK_PARSE("Standard: c++11", Standard, FormatStyle::LS_Cpp11);
12323+
CHECK_PARSE("Standard: c++14", Standard, FormatStyle::LS_Cpp14);
12324+
CHECK_PARSE("Standard: c++17", Standard, FormatStyle::LS_Cpp17);
12325+
CHECK_PARSE("Standard: c++20", Standard, FormatStyle::LS_Cpp20);
12326+
CHECK_PARSE("Standard: Auto", Standard, FormatStyle::LS_Auto);
12327+
CHECK_PARSE("Standard: Latest", Standard, FormatStyle::LS_Latest);
12328+
// Legacy aliases:
1230812329
CHECK_PARSE("Standard: Cpp03", Standard, FormatStyle::LS_Cpp03);
12309-
CHECK_PARSE("Standard: Cpp11", Standard, FormatStyle::LS_Cpp11);
12330+
CHECK_PARSE("Standard: Cpp11", Standard, FormatStyle::LS_Latest);
1231012331
CHECK_PARSE("Standard: C++03", Standard, FormatStyle::LS_Cpp03);
1231112332
CHECK_PARSE("Standard: C++11", Standard, FormatStyle::LS_Cpp11);
12312-
CHECK_PARSE("Standard: Auto", Standard, FormatStyle::LS_Auto);
1231312333

1231412334
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
1231512335
CHECK_PARSE("BreakBeforeBinaryOperators: NonAssignment",

0 commit comments

Comments
 (0)
Please sign in to comment.