Skip to content

Commit bd63dc7

Browse files
SC llvm teamSC llvm team
SC llvm team
authored and
SC llvm team
committed
Merged main:16cf9c9af004 into amd-gfx:251b3d8041ba
Local branch amd-gfx 251b3d8 Merged main:19b664d35266 into amd-gfx:f205aef70eb5 Remote branch main 16cf9c9 [flang][openacc] Support labeled DO loop after acc combined directive (llvm#66296)
2 parents 251b3d8 + 16cf9c9 commit bd63dc7

File tree

30 files changed

+755
-382
lines changed

30 files changed

+755
-382
lines changed

clang/lib/Serialization/ASTReader.cpp

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2489,6 +2489,32 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
24892489
std::optional<int64_t> Old = std::nullopt;
24902490
std::optional<int64_t> New = std::nullopt;
24912491
};
2492+
auto HasInputContentChanged = [&](Change OriginalChange) {
2493+
assert(ValidateASTInputFilesContent &&
2494+
"We should only check the content of the inputs with "
2495+
"ValidateASTInputFilesContent enabled.");
2496+
2497+
if (StoredContentHash == static_cast<uint64_t>(llvm::hash_code(-1)))
2498+
return OriginalChange;
2499+
2500+
auto MemBuffOrError = FileMgr.getBufferForFile(*File);
2501+
if (!MemBuffOrError) {
2502+
if (!Complain)
2503+
return OriginalChange;
2504+
std::string ErrorStr = "could not get buffer for file '";
2505+
ErrorStr += File->getName();
2506+
ErrorStr += "'";
2507+
Error(ErrorStr);
2508+
return OriginalChange;
2509+
}
2510+
2511+
// FIXME: hash_value is not guaranteed to be stable!
2512+
auto ContentHash = hash_value(MemBuffOrError.get()->getBuffer());
2513+
if (StoredContentHash == static_cast<uint64_t>(ContentHash))
2514+
return Change{Change::None};
2515+
2516+
return Change{Change::Content};
2517+
};
24922518
auto HasInputFileChanged = [&]() {
24932519
if (StoredSize != File->getSize())
24942520
return Change{Change::Size, StoredSize, File->getSize()};
@@ -2499,33 +2525,23 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
24992525

25002526
// In case the modification time changes but not the content,
25012527
// accept the cached file as legit.
2502-
if (ValidateASTInputFilesContent &&
2503-
StoredContentHash != static_cast<uint64_t>(llvm::hash_code(-1))) {
2504-
auto MemBuffOrError = FileMgr.getBufferForFile(*File);
2505-
if (!MemBuffOrError) {
2506-
if (!Complain)
2507-
return MTimeChange;
2508-
std::string ErrorStr = "could not get buffer for file '";
2509-
ErrorStr += File->getName();
2510-
ErrorStr += "'";
2511-
Error(ErrorStr);
2512-
return MTimeChange;
2513-
}
2514-
2515-
// FIXME: hash_value is not guaranteed to be stable!
2516-
auto ContentHash = hash_value(MemBuffOrError.get()->getBuffer());
2517-
if (StoredContentHash == static_cast<uint64_t>(ContentHash))
2518-
return Change{Change::None};
2528+
if (ValidateASTInputFilesContent)
2529+
return HasInputContentChanged(MTimeChange);
25192530

2520-
return Change{Change::Content};
2521-
}
25222531
return MTimeChange;
25232532
}
25242533
return Change{Change::None};
25252534
};
25262535

25272536
bool IsOutOfDate = false;
25282537
auto FileChange = SkipChecks ? Change{Change::None} : HasInputFileChanged();
2538+
// When ForceCheckCXX20ModulesInputFiles and ValidateASTInputFilesContent
2539+
// enabled, it is better to check the contents of the inputs. Since we can't
2540+
// get correct modified time information for inputs from overriden inputs.
2541+
if (HSOpts.ForceCheckCXX20ModulesInputFiles && ValidateASTInputFilesContent &&
2542+
F.StandardCXXModule && FileChange.Kind == Change::None)
2543+
FileChange = HasInputContentChanged(FileChange);
2544+
25292545
// For an overridden file, there is nothing to validate.
25302546
if (!Overridden && FileChange.Kind != Change::None) {
25312547
if (Complain && !Diags.isDiagnosticInFlight()) {

clang/unittests/Serialization/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
66
)
77

88
add_clang_unittest(SerializationTests
9+
ForceCheckFileInputTest.cpp
910
InMemoryModuleCacheTest.cpp
1011
ModuleCacheTest.cpp
1112
NoCommentsTest.cpp
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
//===- unittests/Serialization/ForceCheckFileInputTest.cpp - CI tests -----===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "clang/ASTMatchers/ASTMatchFinder.h"
10+
#include "clang/ASTMatchers/ASTMatchers.h"
11+
#include "clang/Basic/FileManager.h"
12+
#include "clang/Frontend/CompilerInstance.h"
13+
#include "clang/Frontend/CompilerInvocation.h"
14+
#include "clang/Frontend/FrontendActions.h"
15+
#include "clang/Frontend/Utils.h"
16+
#include "clang/Lex/HeaderSearch.h"
17+
#include "clang/Lex/PreprocessorOptions.h"
18+
#include "clang/Serialization/ASTReader.h"
19+
#include "clang/Tooling/Tooling.h"
20+
#include "llvm/ADT/SmallString.h"
21+
#include "llvm/Support/FileSystem.h"
22+
#include "llvm/Support/raw_ostream.h"
23+
24+
#include "gtest/gtest.h"
25+
26+
using namespace llvm;
27+
using namespace clang;
28+
29+
namespace {
30+
31+
class ForceCheckFileInputTest : public ::testing::Test {
32+
void SetUp() override {
33+
EXPECT_FALSE(sys::fs::createUniqueDirectory("modules-test", TestDir));
34+
}
35+
36+
void TearDown() override { sys::fs::remove_directories(TestDir); }
37+
38+
public:
39+
SmallString<256> TestDir;
40+
41+
void addFile(StringRef Path, StringRef Contents) {
42+
EXPECT_FALSE(sys::path::is_absolute(Path));
43+
44+
SmallString<256> AbsPath(TestDir);
45+
sys::path::append(AbsPath, Path);
46+
47+
EXPECT_FALSE(
48+
sys::fs::create_directories(llvm::sys::path::parent_path(AbsPath)));
49+
50+
std::error_code EC;
51+
llvm::raw_fd_ostream OS(AbsPath, EC);
52+
EXPECT_FALSE(EC);
53+
OS << Contents;
54+
}
55+
};
56+
57+
TEST_F(ForceCheckFileInputTest, ForceCheck) {
58+
addFile("a.cppm", R"cpp(
59+
export module a;
60+
export int aa = 43;
61+
)cpp");
62+
63+
std::string BMIPath = llvm::Twine(TestDir + "/a.pcm").str();
64+
65+
{
66+
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
67+
CompilerInstance::createDiagnostics(new DiagnosticOptions());
68+
CreateInvocationOptions CIOpts;
69+
CIOpts.Diags = Diags;
70+
CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();
71+
72+
const char *Args[] = {
73+
"clang++", "-std=c++20", "--precompile", "-working-directory",
74+
TestDir.c_str(), "a.cppm", "-o", BMIPath.c_str()};
75+
std::shared_ptr<CompilerInvocation> Invocation =
76+
createInvocation(Args, CIOpts);
77+
EXPECT_TRUE(Invocation);
78+
79+
auto Buf = CIOpts.VFS->getBufferForFile("a.cppm");
80+
EXPECT_TRUE(Buf);
81+
82+
Invocation->getPreprocessorOpts().addRemappedFile("a.cppm", Buf->get());
83+
84+
Buf->release();
85+
86+
CompilerInstance Instance;
87+
Instance.setDiagnostics(Diags.get());
88+
Instance.setInvocation(Invocation);
89+
90+
if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
91+
Instance.getInvocation(), Instance.getDiagnostics(), CIOpts.VFS))
92+
CIOpts.VFS = VFSWithRemapping;
93+
Instance.createFileManager(CIOpts.VFS);
94+
95+
Instance.getHeaderSearchOpts().ValidateASTInputFilesContent = true;
96+
97+
GenerateModuleInterfaceAction Action;
98+
EXPECT_TRUE(Instance.ExecuteAction(Action));
99+
EXPECT_FALSE(Diags->hasErrorOccurred());
100+
}
101+
102+
{
103+
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
104+
CompilerInstance::createDiagnostics(new DiagnosticOptions());
105+
CreateInvocationOptions CIOpts;
106+
CIOpts.Diags = Diags;
107+
CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();
108+
109+
std::string BMIPath = llvm::Twine(TestDir + "/a.pcm").str();
110+
const char *Args[] = {
111+
"clang++", "-std=c++20", "--precompile", "-working-directory",
112+
TestDir.c_str(), "a.cppm", "-o", BMIPath.c_str()};
113+
std::shared_ptr<CompilerInvocation> Invocation =
114+
createInvocation(Args, CIOpts);
115+
EXPECT_TRUE(Invocation);
116+
117+
CompilerInstance Clang;
118+
119+
Clang.setInvocation(Invocation);
120+
Clang.setDiagnostics(Diags.get());
121+
FileManager *FM = Clang.createFileManager(CIOpts.VFS);
122+
Clang.createSourceManager(*FM);
123+
124+
EXPECT_TRUE(Clang.createTarget());
125+
Clang.createPreprocessor(TU_Complete);
126+
Clang.getHeaderSearchOpts().ForceCheckCXX20ModulesInputFiles = true;
127+
Clang.getHeaderSearchOpts().ValidateASTInputFilesContent = true;
128+
Clang.createASTReader();
129+
130+
addFile("a.cppm", R"cpp(
131+
export module a;
132+
export int aa = 44;
133+
)cpp");
134+
135+
auto ReadResult =
136+
Clang.getASTReader()->ReadAST(BMIPath, serialization::MK_MainFile,
137+
SourceLocation(), ASTReader::ARR_None);
138+
139+
// We shall be able to detect the content change here.
140+
EXPECT_NE(ReadResult, ASTReader::Success);
141+
}
142+
}
143+
144+
} // anonymous namespace

flang/include/flang/Parser/parse-tree.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4247,7 +4247,11 @@ struct OpenACCDeclarativeConstruct {
42474247
EMPTY_CLASS(AccEndLoop);
42484248
struct OpenACCLoopConstruct {
42494249
TUPLE_CLASS_BOILERPLATE(OpenACCLoopConstruct);
4250-
std::tuple<AccBeginLoopDirective, DoConstruct, std::optional<AccEndLoop>> t;
4250+
OpenACCLoopConstruct(AccBeginLoopDirective &&a)
4251+
: t({std::move(a), std::nullopt, std::nullopt}) {}
4252+
std::tuple<AccBeginLoopDirective, std::optional<DoConstruct>,
4253+
std::optional<AccEndLoop>>
4254+
t;
42514255
};
42524256

42534257
struct OpenACCStandaloneConstruct {

flang/lib/Lower/DirectivesCommon.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,31 @@ void genOmpAccAtomicCapture(Fortran::lower::AbstractConverter &converter,
587587
firOpBuilder.setInsertionPointToStart(&block);
588588
}
589589

590+
/// Create empty blocks for the current region.
591+
/// These blocks replace blocks parented to an enclosing region.
592+
template <typename... TerminatorOps>
593+
void createEmptyRegionBlocks(
594+
fir::FirOpBuilder &builder,
595+
std::list<Fortran::lower::pft::Evaluation> &evaluationList) {
596+
mlir::Region *region = &builder.getRegion();
597+
for (Fortran::lower::pft::Evaluation &eval : evaluationList) {
598+
if (eval.block) {
599+
if (eval.block->empty()) {
600+
eval.block->erase();
601+
eval.block = builder.createBlock(region);
602+
} else {
603+
[[maybe_unused]] mlir::Operation &terminatorOp = eval.block->back();
604+
assert(mlir::isa<TerminatorOps...>(terminatorOp) &&
605+
"expected terminator op");
606+
}
607+
}
608+
if (!eval.isDirective() && eval.hasNestedEvaluations())
609+
createEmptyRegionBlocks<TerminatorOps...>(builder,
610+
eval.getNestedEvaluations());
611+
}
612+
}
613+
590614
} // namespace lower
591615
} // namespace Fortran
592616

593-
#endif // FORTRAN_LOWER_DIRECTIVES_COMMON_H
617+
#endif // FORTRAN_LOWER_DIRECTIVES_COMMON_H

0 commit comments

Comments
 (0)