summaryrefslogtreecommitdiff
path: root/clang/lib/Format
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Format')
-rw-r--r--clang/lib/Format/BreakableToken.cpp27
-rw-r--r--clang/lib/Format/BreakableToken.h20
-rw-r--r--clang/lib/Format/Format.cpp82
-rw-r--r--clang/lib/Format/FormatToken.h4
-rw-r--r--clang/lib/Format/FormatTokenLexer.cpp12
-rw-r--r--clang/lib/Format/NamespaceEndCommentsFixer.cpp20
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp140
-rw-r--r--clang/lib/Format/UnwrappedLineFormatter.cpp13
-rw-r--r--clang/lib/Format/UnwrappedLineParser.cpp9
9 files changed, 241 insertions, 86 deletions
diff --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp
index 09ea5473c0c1..cd0eb0b4324a 100644
--- a/clang/lib/Format/BreakableToken.cpp
+++ b/clang/lib/Format/BreakableToken.cpp
@@ -88,11 +88,11 @@ getCommentSplit(StringRef Text, unsigned ContentStartColumn,
StringRef::size_type SpaceOffset = Text.find_last_of(Blanks, MaxSplitBytes);
- static auto *const kNumberedListRegexp = new llvm::Regex("^[1-9][0-9]?\\.");
+ static const auto kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\.");
while (SpaceOffset != StringRef::npos) {
// Do not split before a number followed by a dot: this would be interpreted
// as a numbered list, which would prevent re-flowing in subsequent passes.
- if (kNumberedListRegexp->match(Text.substr(SpaceOffset).ltrim(Blanks)))
+ if (kNumberedListRegexp.match(Text.substr(SpaceOffset).ltrim(Blanks)))
SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
// In JavaScript, some @tags can be followed by {, and machinery that parses
// these comments will fail to understand the comment if followed by a line
@@ -245,7 +245,7 @@ BreakableStringLiteral::BreakableStringLiteral(
BreakableToken::Split BreakableStringLiteral::getSplit(
unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
- unsigned ContentStartColumn, llvm::Regex &CommentPragmasRegex) const {
+ unsigned ContentStartColumn, const llvm::Regex &CommentPragmasRegex) const {
return getStringSplit(Line.substr(TailOffset), ContentStartColumn,
ColumnLimit - Postfix.size(), Style.TabWidth, Encoding);
}
@@ -271,7 +271,7 @@ unsigned BreakableComment::getLineCount() const { return Lines.size(); }
BreakableToken::Split
BreakableComment::getSplit(unsigned LineIndex, unsigned TailOffset,
unsigned ColumnLimit, unsigned ContentStartColumn,
- llvm::Regex &CommentPragmasRegex) const {
+ const llvm::Regex &CommentPragmasRegex) const {
// Don't break lines matching the comment pragmas regex.
if (CommentPragmasRegex.match(Content[LineIndex]))
return Split(StringRef::npos, 0);
@@ -316,9 +316,9 @@ static bool mayReflowContent(StringRef Content) {
// Numbered lists may also start with a number followed by '.'
// To avoid issues if a line starts with a number which is actually the end
// of a previous line, we only consider numbers with up to 2 digits.
- static auto *const kNumberedListRegexp = new llvm::Regex("^[1-9][0-9]?\\. ");
+ static const auto kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\. ");
hasSpecialMeaningPrefix =
- hasSpecialMeaningPrefix || kNumberedListRegexp->match(Content);
+ hasSpecialMeaningPrefix || kNumberedListRegexp.match(Content);
// Simple heuristic for what to reflow: content should contain at least two
// characters and either the first or second character must be
@@ -458,7 +458,7 @@ BreakableBlockComment::BreakableBlockComment(
BreakableToken::Split BreakableBlockComment::getSplit(
unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
- unsigned ContentStartColumn, llvm::Regex &CommentPragmasRegex) const {
+ unsigned ContentStartColumn, const llvm::Regex &CommentPragmasRegex) const {
// Don't break lines matching the comment pragmas regex.
if (CommentPragmasRegex.match(Content[LineIndex]))
return Split(StringRef::npos, 0);
@@ -597,9 +597,8 @@ void BreakableBlockComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
PrefixWithTrailingIndent.size());
}
-BreakableToken::Split
-BreakableBlockComment::getReflowSplit(unsigned LineIndex,
- llvm::Regex &CommentPragmasRegex) const {
+BreakableToken::Split BreakableBlockComment::getReflowSplit(
+ unsigned LineIndex, const llvm::Regex &CommentPragmasRegex) const {
if (!mayReflow(LineIndex, CommentPragmasRegex))
return Split(StringRef::npos, 0);
@@ -706,8 +705,8 @@ BreakableBlockComment::getSplitAfterLastLine(unsigned TailOffset) const {
return Split(StringRef::npos, 0);
}
-bool BreakableBlockComment::mayReflow(unsigned LineIndex,
- llvm::Regex &CommentPragmasRegex) const {
+bool BreakableBlockComment::mayReflow(
+ unsigned LineIndex, const llvm::Regex &CommentPragmasRegex) const {
// Content[LineIndex] may exclude the indent after the '*' decoration. In that
// case, we compute the start of the comment pragma manually.
StringRef IndentContent = Content[LineIndex];
@@ -845,7 +844,7 @@ void BreakableLineCommentSection::insertBreak(
}
BreakableComment::Split BreakableLineCommentSection::getReflowSplit(
- unsigned LineIndex, llvm::Regex &CommentPragmasRegex) const {
+ unsigned LineIndex, const llvm::Regex &CommentPragmasRegex) const {
if (!mayReflow(LineIndex, CommentPragmasRegex))
return Split(StringRef::npos, 0);
@@ -955,7 +954,7 @@ void BreakableLineCommentSection::updateNextToken(LineState &State) const {
}
bool BreakableLineCommentSection::mayReflow(
- unsigned LineIndex, llvm::Regex &CommentPragmasRegex) const {
+ unsigned LineIndex, const llvm::Regex &CommentPragmasRegex) const {
// Line comments have the indent as part of the prefix, so we need to
// recompute the start of the line.
StringRef IndentContent = Content[LineIndex];
diff --git a/clang/lib/Format/BreakableToken.h b/clang/lib/Format/BreakableToken.h
index 72852d59f9c4..a6691300de3b 100644
--- a/clang/lib/Format/BreakableToken.h
+++ b/clang/lib/Format/BreakableToken.h
@@ -155,7 +155,7 @@ public:
/// file.
virtual Split getSplit(unsigned LineIndex, unsigned TailOffset,
unsigned ColumnLimit, unsigned ContentStartColumn,
- llvm::Regex &CommentPragmasRegex) const = 0;
+ const llvm::Regex &CommentPragmasRegex) const = 0;
/// Emits the previously retrieved \p Split via \p Whitespaces.
virtual void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
@@ -190,7 +190,7 @@ public:
/// If the split is not contained within one token, for example when reflowing
/// line comments, returns (0, <length>).
virtual Split getReflowSplit(unsigned LineIndex,
- llvm::Regex &CommentPragmasRegex) const {
+ const llvm::Regex &CommentPragmasRegex) const {
return Split(StringRef::npos, 0);
}
@@ -255,7 +255,7 @@ public:
Split getSplit(unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
unsigned ContentStartColumn,
- llvm::Regex &CommentPragmasRegex) const override;
+ const llvm::Regex &CommentPragmasRegex) const override;
void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
unsigned ContentIndent,
WhitespaceManager &Whitespaces) const override;
@@ -298,7 +298,7 @@ public:
unsigned getLineCount() const override;
Split getSplit(unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
unsigned ContentStartColumn,
- llvm::Regex &CommentPragmasRegex) const override;
+ const llvm::Regex &CommentPragmasRegex) const override;
void compressWhitespace(unsigned LineIndex, unsigned TailOffset, Split Split,
WhitespaceManager &Whitespaces) const override;
@@ -309,7 +309,7 @@ protected:
// Checks if the content of line LineIndex may be reflown with the previous
// line.
virtual bool mayReflow(unsigned LineIndex,
- llvm::Regex &CommentPragmasRegex) const = 0;
+ const llvm::Regex &CommentPragmasRegex) const = 0;
// Contains the original text of the lines of the block comment.
//
@@ -363,7 +363,7 @@ public:
Split getSplit(unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
unsigned ContentStartColumn,
- llvm::Regex &CommentPragmasRegex) const override;
+ const llvm::Regex &CommentPragmasRegex) const override;
unsigned getRangeLength(unsigned LineIndex, unsigned Offset,
StringRef::size_type Length,
unsigned StartColumn) const override;
@@ -375,7 +375,7 @@ public:
unsigned ContentIndent,
WhitespaceManager &Whitespaces) const override;
Split getReflowSplit(unsigned LineIndex,
- llvm::Regex &CommentPragmasRegex) const override;
+ const llvm::Regex &CommentPragmasRegex) const override;
void reflow(unsigned LineIndex,
WhitespaceManager &Whitespaces) const override;
bool introducesBreakBeforeToken() const override;
@@ -384,7 +384,7 @@ public:
Split getSplitAfterLastLine(unsigned TailOffset) const override;
bool mayReflow(unsigned LineIndex,
- llvm::Regex &CommentPragmasRegex) const override;
+ const llvm::Regex &CommentPragmasRegex) const override;
// Contains Javadoc annotations that require additional indent when continued
// on multiple lines.
@@ -448,14 +448,14 @@ public:
unsigned ContentIndent,
WhitespaceManager &Whitespaces) const override;
Split getReflowSplit(unsigned LineIndex,
- llvm::Regex &CommentPragmasRegex) const override;
+ const llvm::Regex &CommentPragmasRegex) const override;
void reflow(unsigned LineIndex,
WhitespaceManager &Whitespaces) const override;
void adaptStartOfLine(unsigned LineIndex,
WhitespaceManager &Whitespaces) const override;
void updateNextToken(LineState &State) const override;
bool mayReflow(unsigned LineIndex,
- llvm::Regex &CommentPragmasRegex) const override;
+ const llvm::Regex &CommentPragmasRegex) const override;
private:
// OriginalPrefix[i] contains the original prefix of line i, including
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index cd44c0be85f0..f12bca48c630 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -467,6 +467,7 @@ template <> struct MappingTraits<FormatStyle> {
Style.ConstructorInitializerIndentWidth);
IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
+ IO.mapOptional("DeriveLineEnding", Style.DeriveLineEnding);
IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
IO.mapOptional("DisableFormat", Style.DisableFormat);
IO.mapOptional("ExperimentalAutoDetectBinPacking",
@@ -476,6 +477,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
+ IO.mapOptional("IncludeIsMainSourceRegex",
+ Style.IncludeStyle.IncludeIsMainSourceRegex);
IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
@@ -534,16 +537,21 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("SpacesBeforeTrailingComments",
Style.SpacesBeforeTrailingComments);
IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
+ IO.mapOptional("SpacesInConditionalStatement",
+ Style.SpacesInConditionalStatement);
IO.mapOptional("SpacesInContainerLiterals",
Style.SpacesInContainerLiterals);
IO.mapOptional("SpacesInCStyleCastParentheses",
Style.SpacesInCStyleCastParentheses);
IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
+ IO.mapOptional("SpaceBeforeSquareBrackets",
+ Style.SpaceBeforeSquareBrackets);
IO.mapOptional("Standard", Style.Standard);
IO.mapOptional("StatementMacros", Style.StatementMacros);
IO.mapOptional("TabWidth", Style.TabWidth);
IO.mapOptional("TypenameMacros", Style.TypenameMacros);
+ IO.mapOptional("UseCRLF", Style.UseCRLF);
IO.mapOptional("UseTab", Style.UseTab);
}
};
@@ -760,6 +768,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.ConstructorInitializerIndentWidth = 4;
LLVMStyle.ContinuationIndentWidth = 4;
LLVMStyle.Cpp11BracedListStyle = true;
+ LLVMStyle.DeriveLineEnding = true;
LLVMStyle.DerivePointerAlignment = false;
LLVMStyle.ExperimentalAutoDetectBinPacking = false;
LLVMStyle.FixNamespaceComments = true;
@@ -790,6 +799,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
LLVMStyle.SpacesBeforeTrailingComments = 1;
LLVMStyle.Standard = FormatStyle::LS_Latest;
+ LLVMStyle.UseCRLF = false;
LLVMStyle.UseTab = FormatStyle::UT_Never;
LLVMStyle.ReflowComments = true;
LLVMStyle.SpacesInParentheses = false;
@@ -807,7 +817,9 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
LLVMStyle.SpaceBeforeAssignmentOperators = true;
LLVMStyle.SpaceBeforeCpp11BracedList = false;
+ LLVMStyle.SpaceBeforeSquareBrackets = false;
LLVMStyle.SpacesInAngles = false;
+ LLVMStyle.SpacesInConditionalStatement = false;
LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
LLVMStyle.PenaltyBreakComment = 300;
@@ -1348,7 +1360,11 @@ public:
WhitespaceManager Whitespaces(
Env.getSourceManager(), Style,
- inputUsesCRLF(Env.getSourceManager().getBufferData(Env.getFileID())));
+ Style.DeriveLineEnding
+ ? inputUsesCRLF(
+ Env.getSourceManager().getBufferData(Env.getFileID()),
+ Style.UseCRLF)
+ : Style.UseCRLF);
ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
Env.getSourceManager(), Whitespaces, Encoding,
BinPackInconclusiveFunctions);
@@ -1369,8 +1385,10 @@ public:
}
private:
- static bool inputUsesCRLF(StringRef Text) {
- return Text.count('\r') * 2 > Text.count('\n');
+ static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF) {
+ size_t LF = Text.count('\n');
+ size_t CR = Text.count('\r') * 2;
+ return LF == CR ? DefaultToCRLF : CR > LF;
}
bool
@@ -2600,6 +2618,10 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
if (std::error_code EC = FS->makeAbsolute(Path))
return make_string_error(EC.message());
+ llvm::SmallVector<std::string, 2> FilesToLookFor;
+ FilesToLookFor.push_back(".clang-format");
+ FilesToLookFor.push_back("_clang-format");
+
for (StringRef Directory = Path; !Directory.empty();
Directory = llvm::sys::path::parent_path(Directory)) {
@@ -2609,43 +2631,35 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
continue;
}
- SmallString<128> ConfigFile(Directory);
-
- llvm::sys::path::append(ConfigFile, ".clang-format");
- LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
+ for (const auto &F : FilesToLookFor) {
+ SmallString<128> ConfigFile(Directory);
- Status = FS->status(ConfigFile.str());
- bool FoundConfigFile =
- Status && (Status->getType() == llvm::sys::fs::file_type::regular_file);
- if (!FoundConfigFile) {
- // Try _clang-format too, since dotfiles are not commonly used on Windows.
- ConfigFile = Directory;
- llvm::sys::path::append(ConfigFile, "_clang-format");
+ llvm::sys::path::append(ConfigFile, F);
LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
+
Status = FS->status(ConfigFile.str());
- FoundConfigFile = Status && (Status->getType() ==
- llvm::sys::fs::file_type::regular_file);
- }
- if (FoundConfigFile) {
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
- FS->getBufferForFile(ConfigFile.str());
- if (std::error_code EC = Text.getError())
- return make_string_error(EC.message());
- if (std::error_code ec =
- parseConfiguration(Text.get()->getBuffer(), &Style)) {
- if (ec == ParseError::Unsuitable) {
- if (!UnsuitableConfigFiles.empty())
- UnsuitableConfigFiles.append(", ");
- UnsuitableConfigFiles.append(ConfigFile);
- continue;
+ if (Status &&
+ (Status->getType() == llvm::sys::fs::file_type::regular_file)) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
+ FS->getBufferForFile(ConfigFile.str());
+ if (std::error_code EC = Text.getError())
+ return make_string_error(EC.message());
+ if (std::error_code ec =
+ parseConfiguration(Text.get()->getBuffer(), &Style)) {
+ if (ec == ParseError::Unsuitable) {
+ if (!UnsuitableConfigFiles.empty())
+ UnsuitableConfigFiles.append(", ");
+ UnsuitableConfigFiles.append(ConfigFile);
+ continue;
+ }
+ return make_string_error("Error reading " + ConfigFile + ": " +
+ ec.message());
}
- return make_string_error("Error reading " + ConfigFile + ": " +
- ec.message());
+ LLVM_DEBUG(llvm::dbgs()
+ << "Using configuration file " << ConfigFile << "\n");
+ return Style;
}
- LLVM_DEBUG(llvm::dbgs()
- << "Using configuration file " << ConfigFile << "\n");
- return Style;
}
}
if (!UnsuitableConfigFiles.empty())
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index b11f36559a8b..e9cd327754ef 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -60,6 +60,8 @@ namespace format {
TYPE(JsExponentiationEqual) \
TYPE(JsFatArrow) \
TYPE(JsNonNullAssertion) \
+ TYPE(JsNullishCoalescingOperator) \
+ TYPE(JsNullPropagatingOperator) \
TYPE(JsPrivateIdentifier) \
TYPE(JsTypeColon) \
TYPE(JsTypeOperator) \
@@ -405,7 +407,7 @@ struct FormatToken {
bool isMemberAccess() const {
return isOneOf(tok::arrow, tok::period, tok::arrowstar) &&
!isOneOf(TT_DesignatedInitializerPeriod, TT_TrailingReturnArrow,
- TT_LambdaArrow);
+ TT_LambdaArrow, TT_LeadingJavaAnnotation);
}
bool isUnaryOperator() const {
diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp
index 5d8a77577c0b..ef20ba884fb3 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -100,6 +100,10 @@ void FormatTokenLexer::tryMergePreviousTokens() {
static const tok::TokenKind JSExponentiation[] = {tok::star, tok::star};
static const tok::TokenKind JSExponentiationEqual[] = {tok::star,
tok::starequal};
+ static const tok::TokenKind JSNullPropagatingOperator[] = {tok::question,
+ tok::period};
+ static const tok::TokenKind JSNullishOperator[] = {tok::question,
+ tok::question};
// FIXME: Investigate what token type gives the correct operator priority.
if (tryMergeTokens(JSIdentity, TT_BinaryOperator))
@@ -116,6 +120,14 @@ void FormatTokenLexer::tryMergePreviousTokens() {
Tokens.back()->Tok.setKind(tok::starequal);
return;
}
+ if (tryMergeTokens(JSNullishOperator, TT_JsNullishCoalescingOperator))
+ return;
+ if (tryMergeTokens(JSNullPropagatingOperator,
+ TT_JsNullPropagatingOperator)) {
+ // Treat like a regular "." access.
+ Tokens.back()->Tok.setKind(tok::period);
+ return;
+ }
if (tryMergeJSPrivateIdentifier())
return;
}
diff --git a/clang/lib/Format/NamespaceEndCommentsFixer.cpp b/clang/lib/Format/NamespaceEndCommentsFixer.cpp
index 98901cff2681..20b424f86077 100644
--- a/clang/lib/Format/NamespaceEndCommentsFixer.cpp
+++ b/clang/lib/Format/NamespaceEndCommentsFixer.cpp
@@ -92,24 +92,24 @@ bool validEndComment(const FormatToken *RBraceTok, StringRef NamespaceName,
// Matches a valid namespace end comment.
// Valid namespace end comments don't need to be edited.
- static llvm::Regex *const NamespaceCommentPattern =
- new llvm::Regex("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
- "namespace( +([a-zA-Z0-9:_]+))?\\.? *(\\*/)?$",
- llvm::Regex::IgnoreCase);
- static llvm::Regex *const NamespaceMacroCommentPattern =
- new llvm::Regex("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
- "([a-zA-Z0-9_]+)\\(([a-zA-Z0-9:_]*)\\)\\.? *(\\*/)?$",
- llvm::Regex::IgnoreCase);
+ static const llvm::Regex NamespaceCommentPattern =
+ llvm::Regex("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
+ "namespace( +([a-zA-Z0-9:_]+))?\\.? *(\\*/)?$",
+ llvm::Regex::IgnoreCase);
+ static const llvm::Regex NamespaceMacroCommentPattern =
+ llvm::Regex("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *"
+ "([a-zA-Z0-9_]+)\\(([a-zA-Z0-9:_]*)\\)\\.? *(\\*/)?$",
+ llvm::Regex::IgnoreCase);
SmallVector<StringRef, 8> Groups;
if (NamespaceTok->is(TT_NamespaceMacro) &&
- NamespaceMacroCommentPattern->match(Comment->TokenText, &Groups)) {
+ NamespaceMacroCommentPattern.match(Comment->TokenText, &Groups)) {
StringRef NamespaceTokenText = Groups.size() > 4 ? Groups[4] : "";
// The name of the macro must be used.
if (NamespaceTokenText != NamespaceTok->TokenText)
return false;
} else if (NamespaceTok->isNot(tok::kw_namespace) ||
- !NamespaceCommentPattern->match(Comment->TokenText, &Groups)) {
+ !NamespaceCommentPattern.match(Comment->TokenText, &Groups)) {
// Comment does not match regex.
return false;
}
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 1ed35597d075..d5d394e61926 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -950,9 +950,9 @@ private:
if (CurrentToken->isOneOf(tok::star, tok::amp))
CurrentToken->Type = TT_PointerOrReference;
consumeToken();
- if (CurrentToken &&
- CurrentToken->Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator,
- tok::comma))
+ if (CurrentToken && CurrentToken->Previous->isOneOf(
+ TT_BinaryOperator, TT_UnaryOperator, tok::comma,
+ tok::star, tok::arrow, tok::amp, tok::ampamp))
CurrentToken->Previous->Type = TT_OverloadedOperator;
}
if (CurrentToken) {
@@ -1344,12 +1344,80 @@ private:
Contexts.back().IsExpression = false;
} else if (Current.is(tok::kw_new)) {
Contexts.back().CanBeExpression = false;
- } else if (Current.isOneOf(tok::semi, tok::exclaim)) {
+ } else if (Current.is(tok::semi) ||
+ (Current.is(tok::exclaim) && Current.Previous &&
+ !Current.Previous->is(tok::kw_operator))) {
// This should be the condition or increment in a for-loop.
+ // But not operator !() (can't use TT_OverloadedOperator here as its not
+ // been annotated yet).
Contexts.back().IsExpression = true;
}
}
+ static FormatToken *untilMatchingParen(FormatToken *Current) {
+ // Used when `MatchingParen` is not yet established.
+ int ParenLevel = 0;
+ while (Current) {
+ if (Current->is(tok::l_paren))
+ ParenLevel++;
+ if (Current->is(tok::r_paren))
+ ParenLevel--;
+ if (ParenLevel < 1)
+ break;
+ Current = Current->Next;
+ }
+ return Current;
+ }
+
+ static bool isDeductionGuide(FormatToken &Current) {
+ // Look for a deduction guide template<T> A(...) -> A<...>;
+ if (Current.Previous && Current.Previous->is(tok::r_paren) &&
+ Current.startsSequence(tok::arrow, tok::identifier, tok::less)) {
+ // Find the TemplateCloser.
+ FormatToken *TemplateCloser = Current.Next->Next;
+ int NestingLevel = 0;
+ while (TemplateCloser) {
+ // Skip over an expressions in parens A<(3 < 2)>;
+ if (TemplateCloser->is(tok::l_paren)) {
+ // No Matching Paren yet so skip to matching paren
+ TemplateCloser = untilMatchingParen(TemplateCloser);
+ }
+ if (TemplateCloser->is(tok::less))
+ NestingLevel++;
+ if (TemplateCloser->is(tok::greater))
+ NestingLevel--;
+ if (NestingLevel < 1)
+ break;
+ TemplateCloser = TemplateCloser->Next;
+ }
+ // Assuming we have found the end of the template ensure its followed
+ // with a semi-colon.
+ if (TemplateCloser && TemplateCloser->Next &&
+ TemplateCloser->Next->is(tok::semi) &&
+ Current.Previous->MatchingParen) {
+ // Determine if the identifier `A` prior to the A<..>; is the same as
+ // prior to the A(..)
+ FormatToken *LeadingIdentifier =
+ Current.Previous->MatchingParen->Previous;
+
+ // Differentiate a deduction guide by seeing the
+ // > of the template prior to the leading identifier.
+ if (LeadingIdentifier) {
+ FormatToken *PriorLeadingIdentifier = LeadingIdentifier->Previous;
+ // Skip back past explicit decoration
+ if (PriorLeadingIdentifier &&
+ PriorLeadingIdentifier->is(tok::kw_explicit))
+ PriorLeadingIdentifier = PriorLeadingIdentifier->Previous;
+
+ return (PriorLeadingIdentifier &&
+ PriorLeadingIdentifier->is(TT_TemplateCloser) &&
+ LeadingIdentifier->TokenText == Current.Next->TokenText);
+ }
+ }
+ }
+ return false;
+ }
+
void determineTokenType(FormatToken &Current) {
if (!Current.is(TT_Unknown))
// The token type is already known.
@@ -1397,6 +1465,10 @@ private:
!Current.Previous->is(tok::kw_operator)) {
// not auto operator->() -> xxx;
Current.Type = TT_TrailingReturnArrow;
+
+ } else if (isDeductionGuide(Current)) {
+ // Deduction guides trailing arrow " A(...) -> A<T>;".
+ Current.Type = TT_TrailingReturnArrow;
} else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
Current.Type = determineStarAmpUsage(Current,
Contexts.back().CanBeExpression &&
@@ -1757,7 +1829,8 @@ private:
// Use heuristics to recognize unary operators.
if (PrevToken->isOneOf(tok::equal, tok::l_paren, tok::comma, tok::l_square,
tok::question, tok::colon, tok::kw_return,
- tok::kw_case, tok::at, tok::l_brace, tok::kw_throw))
+ tok::kw_case, tok::at, tok::l_brace, tok::kw_throw,
+ tok::kw_co_return, tok::kw_co_yield))
return TT_UnaryOperator;
// There can't be two consecutive binary operators.
@@ -2087,11 +2160,22 @@ static bool isFunctionDeclarationName(const FormatToken &Current,
continue;
if (Next->isOneOf(tok::kw_new, tok::kw_delete)) {
// For 'new[]' and 'delete[]'.
- if (Next->Next && Next->Next->is(tok::l_square) && Next->Next->Next &&
- Next->Next->Next->is(tok::r_square))
+ if (Next->Next &&
+ Next->Next->startsSequence(tok::l_square, tok::r_square))
Next = Next->Next->Next;
continue;
}
+ if (Next->startsSequence(tok::l_square, tok::r_square)) {
+ // For operator[]().
+ Next = Next->Next;
+ continue;
+ }
+ if ((Next->isSimpleTypeSpecifier() || Next->is(tok::identifier)) &&
+ Next->Next && Next->Next->isOneOf(tok::star, tok::amp, tok::ampamp)) {
+ // For operator void*(), operator char*(), operator Foo*().
+ Next = Next->Next;
+ continue;
+ }
break;
}
@@ -2508,6 +2592,13 @@ bool TokenAnnotator::spaceRequiredBeforeParens(const FormatToken &Right) const {
Right.ParameterCount > 0);
}
+/// Returns \c true if the token is followed by a boolean condition, \c false
+/// otherwise.
+static bool isKeywordWithCondition(const FormatToken &Tok) {
+ return Tok.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch,
+ tok::kw_constexpr);
+}
+
bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
const FormatToken &Left,
const FormatToken &Right) {
@@ -2526,6 +2617,15 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
(Left.is(tok::l_brace) && Left.BlockKind != BK_Block &&
Right.is(tok::r_brace) && Right.BlockKind != BK_Block))
return Style.SpaceInEmptyParentheses;
+ if (Style.SpacesInConditionalStatement) {
+ if (Left.is(tok::l_paren) && Left.Previous &&
+ isKeywordWithCondition(*Left.Previous))
+ return true;
+ if (Right.is(tok::r_paren) && Right.MatchingParen &&
+ Right.MatchingParen->Previous &&
+ isKeywordWithCondition(*Right.MatchingParen->Previous))
+ return true;
+ }
if (Left.is(tok::l_paren) || Right.is(tok::r_paren))
return (Right.is(TT_CastRParen) ||
(Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen)))
@@ -2567,7 +2667,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return Left.Tok.isLiteral() || (Left.is(tok::identifier) && Left.Previous &&
Left.Previous->is(tok::kw_case));
if (Left.is(tok::l_square) && Right.is(tok::amp))
- return false;
+ return Style.SpacesInSquareBrackets;
if (Right.is(TT_PointerOrReference)) {
if (Left.is(tok::r_paren) && Line.MightBeFunctionDecl) {
if (!Left.MatchingParen)
@@ -2605,6 +2705,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
tok::l_square));
if (Right.is(tok::star) && Left.is(tok::l_paren))
return false;
+ if (Right.isOneOf(tok::star, tok::amp, tok::ampamp) &&
+ (Left.is(tok::identifier) || Left.isSimpleTypeSpecifier()) &&
+ Left.Previous && Left.Previous->is(tok::kw_operator))
+ // Space between the type and the *
+ // operator void*(), operator char*(), operator Foo*() dependant
+ // on PointerAlignment style.
+ return (Style.PointerAlignment != FormatStyle::PAS_Left);
const auto SpaceRequiredForArrayInitializerLSquare =
[](const FormatToken &LSquareTok, const FormatStyle &Style) {
return Style.SpacesInContainerLiterals ||
@@ -2634,7 +2741,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
TT_DesignatedInitializerLSquare,
TT_StructuredBindingLSquare, TT_AttributeSquare) &&
- !Left.isOneOf(tok::numeric_constant, TT_DictLiteral))
+ !Left.isOneOf(tok::numeric_constant, TT_DictLiteral) &&
+ !(!Left.is(tok::r_square) && Style.SpaceBeforeSquareBrackets &&
+ Right.is(TT_ArraySubscriptLSquare)))
return false;
if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
return !Left.Children.empty(); // No spaces in "{}".
@@ -2906,14 +3015,18 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return true;
}
if (Left.is(TT_UnaryOperator)) {
- // The alternative operators for ~ and ! are "compl" and "not".
- // If they are used instead, we do not want to combine them with
- // the token to the right, unless that is a left paren.
if (!Right.is(tok::l_paren)) {
+ // The alternative operators for ~ and ! are "compl" and "not".
+ // If they are used instead, we do not want to combine them with
+ // the token to the right, unless that is a left paren.
if (Left.is(tok::exclaim) && Left.TokenText == "not")
return true;
if (Left.is(tok::tilde) && Left.TokenText == "compl")
return true;
+ // Lambda captures allow for a lone &, so "&]" needs to be properly
+ // handled.
+ if (Left.is(tok::amp) && Right.is(tok::r_square))
+ return Style.SpacesInSquareBrackets;
}
return (Style.SpaceAfterLogicalNot && Left.is(tok::exclaim)) ||
Right.is(TT_BinaryOperator);
@@ -2947,7 +3060,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
// The identifier might actually be a macro name such as ALWAYS_INLINE. If
// this turns out to be too lenient, add analysis of the identifier itself.
return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
- if (Right.is(tok::coloncolon) && !Left.isOneOf(tok::l_brace, tok::comment))
+ if (Right.is(tok::coloncolon) &&
+ !Left.isOneOf(tok::l_brace, tok::comment, tok::l_paren))
return (Left.is(TT_TemplateOpener) &&
Style.Standard < FormatStyle::LS_Cpp11) ||
!(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 8b8d357d9cbe..fec85f1174da 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -326,6 +326,19 @@ private:
FormatStyle::BWACS_Always)
? tryMergeSimpleBlock(I, E, Limit)
: 0;
+ } else if (I[1]->First->is(tok::l_brace) &&
+ TheLine->First->isOneOf(tok::kw_else, tok::kw_catch) &&
+ Style.BraceWrapping.AfterControlStatement ==
+ FormatStyle::BWACS_MultiLine) {
+ // This case if different from the upper BWACS_MultiLine processing
+ // in that a preceding r_brace is not on the same line as else/catch
+ // most likely because of BeforeElse/BeforeCatch set to true.
+ // If the line length doesn't fit ColumnLimit, leave l_brace on the
+ // next line to respect the BWACS_MultiLine.
+ return (Style.ColumnLimit == 0 ||
+ TheLine->Last->TotalLength <= Style.ColumnLimit)
+ ? 1
+ : 0;
}
// Try to merge either empty or one-line block if is precedeed by control
// statement token
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index bbe05602f6da..ead6b4743207 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -466,7 +466,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
(NextTok->is(tok::semi) &&
(!ExpectClassBody || LBraceStack.size() != 1)) ||
(NextTok->isBinaryOperator() && !NextIsObjCMethod);
- if (NextTok->is(tok::l_square)) {
+ if (!Style.isCSharp() && NextTok->is(tok::l_square)) {
// We can have an array subscript after a braced init
// list, but C++11 attributes are expected after blocks.
NextTok = Tokens->getNextToken();
@@ -2498,9 +2498,10 @@ bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {
// Checks if \p FormatTok is a line comment that continues the line comment
// section on \p Line.
-static bool continuesLineCommentSection(const FormatToken &FormatTok,
- const UnwrappedLine &Line,
- llvm::Regex &CommentPragmasRegex) {
+static bool
+continuesLineCommentSection(const FormatToken &FormatTok,
+ const UnwrappedLine &Line,
+ const llvm::Regex &CommentPragmasRegex) {
if (Line.Tokens.empty())
return false;