Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -3324,6 +3324,16 @@ auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {}; + auto applyChildFormatTexts = [&](FormatStyle *Style) { + for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) { + auto EC = parseConfiguration(*MemBuf, Style, AllowUnknownOptions, + dropDiagnosticHandler); + // It was already correctly parsed. + assert(!EC); + static_cast(EC); + } + }; + for (StringRef Directory = Path; !Directory.empty(); Directory = llvm::sys::path::parent_path(Directory)) { @@ -3363,14 +3373,7 @@ return Style; LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n"); - - for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) { - auto Ec = parseConfiguration(*MemBuf, &Style, AllowUnknownOptions, - dropDiagnosticHandler); - // It was already correctly parsed. - assert(!Ec); - static_cast(Ec); - } + applyChildFormatTexts(&Style); return Style; } @@ -3396,17 +3399,9 @@ UnsuitableConfigFiles); if (!ChildFormatTextToApply.empty()) { - assert(ChildFormatTextToApply.size() == 1); - LLVM_DEBUG(llvm::dbgs() - << "Applying child configuration on fallback style\n"); - - auto Ec = - parseConfiguration(*ChildFormatTextToApply.front(), &FallbackStyle, - AllowUnknownOptions, dropDiagnosticHandler); - // It was already correctly parsed. - assert(!Ec); - static_cast(Ec); + << "Applying child configurations on fallback style\n"); + applyChildFormatTexts(&FallbackStyle); } return FallbackStyle; Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -21480,8 +21480,8 @@ ASSERT_TRUE((bool)StyleTd); ASSERT_EQ(*StyleTd, getLLVMStyle(FormatStyle::LK_TableGen)); - // Test 9.1: overwriting a file style, when parent no file exists with no - // fallback style + // Test 9.1.1: overwriting a file style, when no parent file exists with no + // fallback style. ASSERT_TRUE(FS.addFile( "/e/sub/.clang-format", 0, llvm::MemoryBuffer::getMemBuffer("BasedOnStyle: InheritParentConfig\n" @@ -21496,6 +21496,25 @@ return Style; }()); + // Test 9.1.2: propagate more than one level with no parent file. + ASSERT_TRUE(FS.addFile("/e/sub/sub/code.cpp", 0, + llvm::MemoryBuffer::getMemBuffer("int i;"))); + ASSERT_TRUE(FS.addFile("/e/sub/sub/.clang-format", 0, + llvm::MemoryBuffer::getMemBuffer( + "BasedOnStyle: InheritParentConfig\n" + "WhitespaceSensitiveMacros: ['FOO', 'BAR']"))); + std::vector NonDefaultWhiteSpaceMacros{"FOO", "BAR"}; + + ASSERT_NE(Style9->WhitespaceSensitiveMacros, NonDefaultWhiteSpaceMacros); + Style9 = getStyle("file", "/e/sub/sub/code.cpp", "none", "", &FS); + ASSERT_TRUE(static_cast(Style9)); + ASSERT_EQ(*Style9, [&NonDefaultWhiteSpaceMacros] { + auto Style = getNoStyle(); + Style.ColumnLimit = 20; + Style.WhitespaceSensitiveMacros = NonDefaultWhiteSpaceMacros; + return Style; + }()); + // Test 9.2: with LLVM fallback style Style9 = getStyle("file", "/e/sub/code.cpp", "LLVM", "", &FS); ASSERT_TRUE(static_cast(Style9)); @@ -21519,15 +21538,7 @@ return Style; }()); - // Test 9.4: propagate more than one level - ASSERT_TRUE(FS.addFile("/e/sub/sub/code.cpp", 0, - llvm::MemoryBuffer::getMemBuffer("int i;"))); - ASSERT_TRUE(FS.addFile("/e/sub/sub/.clang-format", 0, - llvm::MemoryBuffer::getMemBuffer( - "BasedOnStyle: InheritParentConfig\n" - "WhitespaceSensitiveMacros: ['FOO', 'BAR']"))); - std::vector NonDefaultWhiteSpaceMacros{"FOO", "BAR"}; - + // Test 9.4: propagate more than one level with a parent file. const auto SubSubStyle = [&NonDefaultWhiteSpaceMacros] { auto Style = getGoogleStyle(); Style.ColumnLimit = 20;