diff --git a/.arclint b/.arclint --- a/.arclint +++ b/.arclint @@ -2,7 +2,7 @@ "linters": { "clang-format": { "type": "script-and-regex", - "script-and-regex.script": "bash utils/arcanist/clang-format.sh", + "script-and-regex.script": "cmd utils\\arcanist\\clang-format.sh", "script-and-regex.regex": "/^(?P[[:alpha:]]+)\n(?P[^\n]+)\n(====|(?P\\d),(?P\\d)\n(?P.*)>>>>\n(?P.*)<<<<\n)$/s", "include": [ "(\\.(cc|cpp|h)$)" diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2645,7 +2645,9 @@ enum LanguageKind : unsigned char { /// Do not use. LK_None, - /// Should be used for C, C++. + /// Should be used for C. + LK_C, + /// Should be used for C++. LK_Cpp, /// Should be used for C#. LK_CSharp, @@ -2666,6 +2668,8 @@ /// (https://developers.google.com/protocol-buffers/). LK_TextProto }; + + bool isC() const { return Language == LK_C; } bool isCpp() const { return Language == LK_Cpp || Language == LK_ObjC; } bool isCSharp() const { return Language == LK_CSharp; } bool isJson() const { return Language == LK_Json; } @@ -4183,6 +4187,8 @@ // Returns a string representation of ``Language``. inline StringRef getLanguageName(FormatStyle::LanguageKind Language) { switch (Language) { + case FormatStyle::LK_C: + return "C"; case FormatStyle::LK_Cpp: return "C++"; case FormatStyle::LK_CSharp: diff --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp --- a/clang/lib/Format/BreakableToken.cpp +++ b/clang/lib/Format/BreakableToken.cpp @@ -110,7 +110,7 @@ // -Wcomment. // Avoid introducing multiline comments by not allowing a break right // after '\'. - if (Style.isCpp()) { + if (Style.isCpp() || Style.isC()) { StringRef::size_type LastNonBlank = Text.find_last_not_of(Blanks, SpaceOffset); if (LastNonBlank != StringRef::npos && Text[LastNonBlank] == '\\') { diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -356,7 +356,7 @@ return false; if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) || (Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) && - Style.isCpp() && + (Style.isCpp() || Style.isC()) && // FIXME: This is a temporary workaround for the case where clang-format // sets BreakBeforeParameter to avoid bin packing and this creates a // completely unnecessary line break after a template type that isn't @@ -917,7 +917,8 @@ // Any break on this level means that the parent level has been broken // and we need to avoid bin packing there. bool NestedBlockSpecialCase = - (!Style.isCpp() && Current.is(tok::r_brace) && State.Stack.size() > 1 && + (!Style.isCpp() && !Style.isC() && Current.is(tok::r_brace) && + State.Stack.size() > 1 && State.Stack[State.Stack.size() - 2].NestedBlockInlined) || (Style.Language == FormatStyle::LK_ObjC && Current.is(tok::r_brace) && State.Stack.size() > 1 && !Style.ObjCBreakBeforeNestedBlockParam); diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -57,6 +57,7 @@ namespace yaml { template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) { + IO.enumCase(Value, "C", FormatStyle::LK_C); IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp); IO.enumCase(Value, "Java", FormatStyle::LK_Java); IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript); @@ -2914,7 +2915,7 @@ tooling::Replacements fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style) { - if (!Style.isCpp()) + if (!Style.isCpp() && !Style.isC()) return Replaces; tooling::Replacements HeaderInsertions; @@ -3040,7 +3041,8 @@ AnalyzerPass; SmallVector Passes; - if (Style.isCpp() && Style.QualifierAlignment != FormatStyle::QAS_Leave) { + if ((Style.isCpp() || Style.isC()) && + Style.QualifierAlignment != FormatStyle::QAS_Leave) { Passes.emplace_back([&](const Environment &Env) { return QualifierAlignmentFixer(Env, Expanded, Code, Ranges, FirstStartColumn, NextStartColumn, @@ -3126,7 +3128,8 @@ ArrayRef Ranges, StringRef FileName) { // cleanups only apply to C++ (they mostly concern ctor commas etc.) - if (Style.Language != FormatStyle::LK_Cpp) + if (Style.Language != FormatStyle::LK_Cpp && + Style.Language != FormatStyle::LK_C) return tooling::Replacements(); auto Env = Environment::make(Code, FileName, Ranges); if (!Env) @@ -3190,7 +3193,7 @@ LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20; LangOpts.LineComment = 1; - bool AlternativeOperators = Style.isCpp(); + bool AlternativeOperators = Style.isCpp() || Style.isC(); LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; LangOpts.Bool = 1; LangOpts.ObjC = 1; diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -104,7 +104,7 @@ return; if (tryMergeForEach()) return; - if (Style.isCpp() && tryTransformTryUsageForC()) + if ((Style.isCpp() || Style.isC()) && tryTransformTryUsageForC()) return; if (Style.isJavaScript() || Style.isCSharp()) { @@ -1023,7 +1023,7 @@ Column = FormatTok->LastLineColumnWidth; } - if (Style.isCpp()) { + if (Style.isCpp() || Style.isC()) { auto it = Macros.find(FormatTok->Tok.getIdentifierInfo()); if (!(Tokens.size() > 0 && Tokens.back()->Tok.getIdentifierInfo() && Tokens.back()->Tok.getIdentifierInfo()->getPPKeywordID() == diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -799,7 +799,8 @@ if (Previous->is(TT_JsTypeOptionalQuestion)) Previous = Previous->getPreviousNonComment(); if ((CurrentToken->is(tok::colon) && - (!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) || + (!Contexts.back().ColonIsDictLiteral || + (!Style.isCpp() && !Style.isC()))) || Style.Language == FormatStyle::LK_Proto || Style.Language == FormatStyle::LK_TextProto) { Left->setType(TT_DictLiteral); @@ -1873,7 +1874,7 @@ /// Determine whether ')' is ending a cast. bool rParenEndsCast(const FormatToken &Tok) { // C-style casts are only used in C++, C# and Java. - if (!Style.isCSharp() && !Style.isCpp() && + if (!Style.isCSharp() && !Style.isCpp() && !Style.isC() && Style.Language != FormatStyle::LK_Java) return false; @@ -2566,7 +2567,8 @@ calculateArrayInitializerColumnList(Line); while (Current) { - if (isFunctionDeclarationName(Style.isCpp(), *Current, Line)) + if (isFunctionDeclarationName((Style.isCpp() || Style.isC()), *Current, + Line)) Current->setType(TT_FunctionDeclarationName); const FormatToken *Prev = Current->Previous; if (Current->is(TT_LineComment)) { @@ -3233,7 +3235,8 @@ if (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch)) return Style.SpaceBeforeParensOptions.AfterControlStatements || spaceRequiredBeforeParens(Right); - if (Left.isOneOf(tok::kw_new, tok::kw_delete)) + if (Style.Language != FormatStyle::LK_C && + Left.isOneOf(tok::kw_new, tok::kw_delete)) return Style.SpaceBeforeParens != FormatStyle::SBPO_Never || spaceRequiredBeforeParens(Right); } @@ -3813,7 +3816,8 @@ if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next && Right.Next->is(tok::string_literal)) return true; - } else if (Style.Language == FormatStyle::LK_Cpp || + } else if (Style.Language == FormatStyle::LK_C || + Style.Language == FormatStyle::LK_Cpp || Style.Language == FormatStyle::LK_ObjC || Style.Language == FormatStyle::LK_Proto || Style.Language == FormatStyle::LK_TableGen || diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -97,7 +97,8 @@ /// For example, 'public:' labels in classes are offset by 1 or 2 /// characters to the left from their level. int getIndentOffset(const FormatToken &RootToken) { - if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || + if (Style.Language == FormatStyle::LK_C || + Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || Style.isCSharp()) return 0; if (RootToken.isAccessSpecifier(false) || diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1218,7 +1218,8 @@ case tok::kw_public: case tok::kw_protected: case tok::kw_private: - if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || + if (Style.Language == FormatStyle::LK_C || + Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || Style.isCSharp()) nextToken(); else @@ -1450,7 +1451,7 @@ if (!parseEnum()) break; // This only applies for C++. - if (!Style.isCpp()) { + if (!Style.isCpp() && !Style.isC()) { addUnwrappedLine(); return; } @@ -1493,7 +1494,8 @@ parseParens(); // Break the unwrapped line if a K&R C function definition has a parameter // declaration. - if (!IsTopLevel || !Style.isCpp() || !Previous || FormatTok->is(tok::eof)) + if (!IsTopLevel || (!Style.isCpp() && !Style.isC()) || !Previous || + FormatTok->is(tok::eof)) break; if (isC78ParameterDecl(FormatTok, Tokens->peekNextToken(), Previous)) { addUnwrappedLine(); @@ -1601,7 +1603,7 @@ break; } - if (Style.isCpp() && FormatTok->is(TT_StatementMacro)) { + if ((Style.isCpp() || Style.isC()) && FormatTok->is(TT_StatementMacro)) { parseStatementMacro(); return; } @@ -2647,7 +2649,7 @@ nextToken(); // If there are two identifiers in a row, this is likely an elaborate // return type. In Java, this can be "implements", etc. - if (Style.isCpp() && FormatTok->is(tok::identifier)) + if ((Style.isCpp() || Style.isC()) && FormatTok->is(tok::identifier)) return false; } } diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -121,6 +121,12 @@ Verbose("verbose", cl::desc("If set, shows the list of processed files"), cl::cat(ClangFormatCategory)); +static cl::opt + SetLanguage("set-language", + cl::desc("Manually sets the programming language clang-format " + "interprets files as"), + cl::init(""), cl::cat(ClangFormatCategory)); + // Use --dry-run to match other LLVM tools when you mean do it but don't // actually do it static cl::opt @@ -458,6 +464,12 @@ Replacements Replaces = sortIncludes(*FormatStyle, Code->getBuffer(), Ranges, AssumedFileName, &CursorPosition); + if (SetLanguage.getNumOccurrences() != 0) { + + if (SetLanguage.getValue() == "C" || SetLanguage.getValue() == "c") { + FormatStyle->Language = FormatStyle::LK_C; + } + } // To format JSON insert a variable to trick the code into thinking its // JavaScript. if (FormatStyle->isJson() && !FormatStyle->DisableFormat) {