@@ -401,6 +401,7 @@ template <> struct MappingTraits<FormatStyle::KeepEmptyLinesStyle> {
401401
402402template <> struct ScalarEnumerationTraits <FormatStyle::LanguageKind> {
403403 static void enumeration (IO &IO, FormatStyle::LanguageKind &Value) {
404+ IO.enumCase (Value, " C" , FormatStyle::LK_C);
404405 IO.enumCase (Value, " Cpp" , FormatStyle::LK_Cpp);
405406 IO.enumCase (Value, " Java" , FormatStyle::LK_Java);
406407 IO.enumCase (Value, " JavaScript" , FormatStyle::LK_JavaScript);
@@ -3952,7 +3953,12 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
39523953 LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11;
39533954
39543955 LangOpts.LineComment = 1 ;
3955- LangOpts.CXXOperatorNames = Style.isCpp ();
3956+
3957+ const auto Language = Style.Language ;
3958+ LangOpts.C17 = Language == FormatStyle::LK_C;
3959+ LangOpts.CXXOperatorNames =
3960+ Language == FormatStyle::LK_Cpp || Language == FormatStyle::LK_ObjC;
3961+
39563962 LangOpts.Bool = 1 ;
39573963 LangOpts.ObjC = 1 ;
39583964 LangOpts.MicrosoftExt = 1 ; // To get kw___try, kw___finally.
@@ -3977,6 +3983,8 @@ const char *StyleOptionHelpDescription =
39773983 " --style=\" {BasedOnStyle: llvm, IndentWidth: 8}\" " ;
39783984
39793985static FormatStyle::LanguageKind getLanguageByFileName (StringRef FileName) {
3986+ if (FileName.ends_with (" .c" ))
3987+ return FormatStyle::LK_C;
39803988 if (FileName.ends_with (" .java" ))
39813989 return FormatStyle::LK_Java;
39823990 if (FileName.ends_with_insensitive (" .js" ) ||
@@ -4016,6 +4024,35 @@ static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
40164024 return FormatStyle::LK_Cpp;
40174025}
40184026
4027+ static FormatStyle::LanguageKind getLanguageByComment (const Environment &Env) {
4028+ const auto ID = Env.getFileID ();
4029+ const auto &SourceMgr = Env.getSourceManager ();
4030+
4031+ LangOptions LangOpts;
4032+ LangOpts.CPlusPlus = 1 ;
4033+ LangOpts.LineComment = 1 ;
4034+
4035+ Lexer Lex (ID, SourceMgr.getBufferOrFake (ID), SourceMgr, LangOpts);
4036+ Lex.SetCommentRetentionState (true );
4037+
4038+ for (Token Tok; !Lex.LexFromRawLexer (Tok) && Tok.is (tok::comment);) {
4039+ auto Text = StringRef (SourceMgr.getCharacterData (Tok.getLocation ()),
4040+ Tok.getLength ());
4041+ if (!Text.consume_front (" // clang-format Language:" ))
4042+ continue ;
4043+
4044+ Text = Text.trim ();
4045+ if (Text == " C" )
4046+ return FormatStyle::LK_C;
4047+ if (Text == " Cpp" )
4048+ return FormatStyle::LK_Cpp;
4049+ if (Text == " ObjC" )
4050+ return FormatStyle::LK_ObjC;
4051+ }
4052+
4053+ return FormatStyle::LK_None;
4054+ }
4055+
40194056FormatStyle::LanguageKind guessLanguage (StringRef FileName, StringRef Code) {
40204057 const auto GuessedLanguage = getLanguageByFileName (FileName);
40214058 if (GuessedLanguage == FormatStyle::LK_Cpp) {
@@ -4025,6 +4062,10 @@ FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
40254062 if (!Code.empty () && (Extension.empty () || Extension == " .h" )) {
40264063 auto NonEmptyFileName = FileName.empty () ? " guess.h" : FileName;
40274064 Environment Env (Code, NonEmptyFileName, /* Ranges=*/ {});
4065+ if (const auto Language = getLanguageByComment (Env);
4066+ Language != FormatStyle::LK_None) {
4067+ return Language;
4068+ }
40284069 ObjCHeaderStyleGuesser Guesser (Env, getLLVMStyle ());
40294070 Guesser.process ();
40304071 if (Guesser.isObjC ())
0 commit comments