diff options
| author | Yong He <yonghe@outlook.com> | 2025-10-10 17:31:01 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-11 00:31:01 +0000 |
| commit | fb34bafd37e3509d51686ee2a5392d2d8e29d7c5 (patch) | |
| tree | ca16f2f53595d730319396320b21ad15fada7a06 /source/slang/slang-preprocessor.cpp | |
| parent | c99addbf2e8a0210b97dad2827045dad95765d08 (diff) | |
Add diagnostic for cyclic #include. (#8679)
Diffstat (limited to 'source/slang/slang-preprocessor.cpp')
| -rw-r--r-- | source/slang/slang-preprocessor.cpp | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/source/slang/slang-preprocessor.cpp b/source/slang/slang-preprocessor.cpp index a0e80473d..ff3e5294e 100644 --- a/source/slang/slang-preprocessor.cpp +++ b/source/slang/slang-preprocessor.cpp @@ -1288,6 +1288,10 @@ struct Preprocessor /// stop them from being included again. HashSet<String> pragmaOnceUniqueIdentities; + /// The unique identities of any paths that have been included already. + /// This is used to detect cycles in #includes. + HashSet<String> includedFiles; + WarningStateTracker* warningStateTracker = nullptr; /// Name pool to use when creating `Name`s from strings @@ -1316,7 +1320,7 @@ struct Preprocessor SourceLoc::RawValue absoluteSourceLocCounter = 0; /// Push a new input file onto the input stack of the preprocessor - void pushInputFile(InputFile* inputFile, SourceLoc location); + void pushInputFile(InputFile* inputFile, SourceLoc location, String fileIdentity); /// Pop the inner-most input file from the stack of input files void popInputFile(); @@ -3479,7 +3483,7 @@ static SlangResult readFile( return SLANG_OK; } -void Preprocessor::pushInputFile(InputFile* inputFile, SourceLoc loc) +void Preprocessor::pushInputFile(InputFile* inputFile, SourceLoc loc, String fileIdentity) { if (m_currentInputFile) { @@ -3488,13 +3492,12 @@ void Preprocessor::pushInputFile(InputFile* inputFile, SourceLoc loc) absoluteSourceLocCounter += offset; } - { - SourceView* sourceView = inputFile->getLexer()->m_sourceView; - sourceView->setAbsoluteLocationBase(absoluteSourceLocCounter); - } + SourceView* sourceView = inputFile->getLexer()->m_sourceView; + sourceView->setAbsoluteLocationBase(absoluteSourceLocCounter); inputFile->m_parent = m_currentInputFile; m_currentInputFile = inputFile; + includedFiles.add(fileIdentity); } // Handle a `#include` directive @@ -3600,6 +3603,17 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context) sourceManager->addSourceFile(filePathInfo.uniqueIdentity, sourceFile); } + auto fileIdentity = sourceFile->getPathInfo().getMostUniqueIdentity(); + if (context->m_preprocessor->includedFiles.contains(fileIdentity)) + { + // This file has already been included, we should diagnose an error and return. + GetSink(context)->diagnose( + pathToken.loc, + Diagnostics::cyclicInclude, + pathToken.getContent()); + return; + } + // If we are running the preprocessor as part of compiling a // specific module, then we must keep track of the file we've // read as yet another file that the module will depend on. @@ -3615,7 +3629,7 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context) InputFile* inputFile = new InputFile(context->m_preprocessor, sourceView); - context->m_preprocessor->pushInputFile(inputFile, directiveLoc); + context->m_preprocessor->pushInputFile(inputFile, directiveLoc, fileIdentity); } static void _parseMacroOps( @@ -4624,6 +4638,7 @@ void Preprocessor::popInputFile() auto lastSegment = sourceView->getLastSegment(); absoluteSourceLocCounter += SourceRange(lastSegment.begin, sourceView->getRange().end).getSize(); + includedFiles.remove(sourceView->getSourceFile()->getPathInfo().getMostUniqueIdentity()); } // We will update the current file to the parent of whatever @@ -4957,7 +4972,10 @@ TokenList preprocessSource( // create an initial input stream based on the provided buffer InputFile* primaryInputFile = new InputFile(&preprocessor, sourceView); - preprocessor.pushInputFile(primaryInputFile, sourceView->getRange().begin); + preprocessor.pushInputFile( + primaryInputFile, + sourceView->getRange().begin, + file->getPathInfo().getMostUniqueIdentity()); } TokenList tokens = ReadAllTokens(&preprocessor); |
