diff options
Diffstat (limited to 'clang/unittests/Frontend/FrontendActionTest.cpp')
-rw-r--r-- | clang/unittests/Frontend/FrontendActionTest.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/clang/unittests/Frontend/FrontendActionTest.cpp b/clang/unittests/Frontend/FrontendActionTest.cpp index 39a131f4a64..c3e6adb6324 100644 --- a/clang/unittests/Frontend/FrontendActionTest.cpp +++ b/clang/unittests/Frontend/FrontendActionTest.cpp @@ -13,6 +13,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/FrontendActions.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Sema/Sema.h" @@ -192,4 +193,66 @@ TEST(PreprocessorFrontendAction, EndSourceFile) { ASSERT_TRUE(TestAction.SeenEnd); } +class TypoExternalSemaSource : public ExternalSemaSource { + CompilerInstance &CI; + +public: + TypoExternalSemaSource(CompilerInstance &CI) : CI(CI) {} + + TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, int LookupKind, + Scope *S, CXXScopeSpec *SS, + CorrectionCandidateCallback &CCC, + DeclContext *MemberContext, bool EnteringContext, + const ObjCObjectPointerType *OPT) override { + // Generate a fake typo correction with one attached note. + ASTContext &Ctx = CI.getASTContext(); + TypoCorrection TC(DeclarationName(&Ctx.Idents.get("moo"))); + unsigned DiagID = Ctx.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Note, "This is a note"); + TC.addExtraDiagnostic(PartialDiagnostic(DiagID, Ctx.getDiagAllocator())); + return TC; + } +}; + +struct TypoDiagnosticConsumer : public DiagnosticConsumer { + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override { + // Capture errors and notes. There should be one of each. + if (DiagLevel == DiagnosticsEngine::Error) { + assert(Error.empty()); + Info.FormatDiagnostic(Error); + } else { + assert(Note.empty()); + Info.FormatDiagnostic(Note); + } + } + SmallString<32> Error; + SmallString<32> Note; +}; + +TEST(ASTFrontendAction, ExternalSemaSource) { + auto *Invocation = new CompilerInvocation; + Invocation->getLangOpts()->CPlusPlus = true; + Invocation->getPreprocessorOpts().addRemappedFile( + "test.cc", MemoryBuffer::getMemBuffer("void fooo();\n" + "int main() { foo(); }") + .release()); + Invocation->getFrontendOpts().Inputs.push_back( + FrontendInputFile("test.cc", IK_CXX)); + Invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly; + Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; + CompilerInstance Compiler; + Compiler.setInvocation(Invocation); + auto *TDC = new TypoDiagnosticConsumer; + Compiler.createDiagnostics(TDC, /*ShouldOwnClient=*/true); + Compiler.setExternalSemaSource(new TypoExternalSemaSource(Compiler)); + + SyntaxOnlyAction TestAction; + ASSERT_TRUE(Compiler.ExecuteAction(TestAction)); + // There should be one error correcting to 'moo' and a note attached to it. + EXPECT_EQ("use of undeclared identifier 'foo'; did you mean 'moo'?", + TDC->Error.str().str()); + EXPECT_EQ("This is a note", TDC->Note.str().str()); +} + } // anonymous namespace |