184f2271aSYitzhak Mandelbaum //===- unittest/Tooling/SourceCodeTest.cpp --------------------------------===//
284f2271aSYitzhak Mandelbaum //
384f2271aSYitzhak Mandelbaum // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
484f2271aSYitzhak Mandelbaum // See https://llvm.org/LICENSE.txt for license information.
584f2271aSYitzhak Mandelbaum // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
684f2271aSYitzhak Mandelbaum //
784f2271aSYitzhak Mandelbaum //===----------------------------------------------------------------------===//
884f2271aSYitzhak Mandelbaum
9fbdf8352SYitzhak Mandelbaum #include "clang/Tooling/Transformer/SourceCode.h"
1084f2271aSYitzhak Mandelbaum #include "TestVisitor.h"
1184f2271aSYitzhak Mandelbaum #include "clang/Basic/Diagnostic.h"
12ecfa0b24SGabriel Matute #include "clang/Basic/SourceLocation.h"
13ecfa0b24SGabriel Matute #include "clang/Lex/Lexer.h"
142e97a1e1SYitzhak Mandelbaum #include "llvm/Testing/Support/Annotations.h"
15b9d2bf38SYitzhak Mandelbaum #include "llvm/Testing/Support/Error.h"
162e97a1e1SYitzhak Mandelbaum #include "llvm/Testing/Support/SupportHelpers.h"
172e97a1e1SYitzhak Mandelbaum #include <gmock/gmock.h>
182e97a1e1SYitzhak Mandelbaum #include <gtest/gtest.h>
1984f2271aSYitzhak Mandelbaum
2084f2271aSYitzhak Mandelbaum using namespace clang;
2184f2271aSYitzhak Mandelbaum
22b9d2bf38SYitzhak Mandelbaum using llvm::Failed;
23b9d2bf38SYitzhak Mandelbaum using llvm::Succeeded;
242e97a1e1SYitzhak Mandelbaum using llvm::ValueIs;
2538b4516dSYitzhak Mandelbaum using tooling::getAssociatedRange;
26ecfa0b24SGabriel Matute using tooling::getExtendedRange;
2784f2271aSYitzhak Mandelbaum using tooling::getExtendedText;
282e97a1e1SYitzhak Mandelbaum using tooling::getRangeForEdit;
292e97a1e1SYitzhak Mandelbaum using tooling::getText;
30ecfa0b24SGabriel Matute using tooling::maybeExtendRange;
31b9d2bf38SYitzhak Mandelbaum using tooling::validateEditRange;
3284f2271aSYitzhak Mandelbaum
3384f2271aSYitzhak Mandelbaum namespace {
3484f2271aSYitzhak Mandelbaum
352e97a1e1SYitzhak Mandelbaum struct IntLitVisitor : TestVisitor<IntLitVisitor> {
VisitIntegerLiteral__anon42750e5d0111::IntLitVisitor362e97a1e1SYitzhak Mandelbaum bool VisitIntegerLiteral(IntegerLiteral *Expr) {
372e97a1e1SYitzhak Mandelbaum OnIntLit(Expr, Context);
382e97a1e1SYitzhak Mandelbaum return true;
392e97a1e1SYitzhak Mandelbaum }
402e97a1e1SYitzhak Mandelbaum
412e97a1e1SYitzhak Mandelbaum std::function<void(IntegerLiteral *, ASTContext *Context)> OnIntLit;
422e97a1e1SYitzhak Mandelbaum };
432e97a1e1SYitzhak Mandelbaum
4484f2271aSYitzhak Mandelbaum struct CallsVisitor : TestVisitor<CallsVisitor> {
VisitCallExpr__anon42750e5d0111::CallsVisitor4584f2271aSYitzhak Mandelbaum bool VisitCallExpr(CallExpr *Expr) {
4684f2271aSYitzhak Mandelbaum OnCall(Expr, Context);
4784f2271aSYitzhak Mandelbaum return true;
4884f2271aSYitzhak Mandelbaum }
4984f2271aSYitzhak Mandelbaum
5084f2271aSYitzhak Mandelbaum std::function<void(CallExpr *, ASTContext *Context)> OnCall;
5184f2271aSYitzhak Mandelbaum };
5284f2271aSYitzhak Mandelbaum
532e97a1e1SYitzhak Mandelbaum // Equality matcher for `clang::CharSourceRange`, which lacks `operator==`.
542e97a1e1SYitzhak Mandelbaum MATCHER_P(EqualsRange, R, "") {
552e97a1e1SYitzhak Mandelbaum return arg.isTokenRange() == R.isTokenRange() &&
562e97a1e1SYitzhak Mandelbaum arg.getBegin() == R.getBegin() && arg.getEnd() == R.getEnd();
572e97a1e1SYitzhak Mandelbaum }
582e97a1e1SYitzhak Mandelbaum
59ecfa0b24SGabriel Matute MATCHER_P2(EqualsAnnotatedRange, Context, R, "") {
6038b4516dSYitzhak Mandelbaum if (arg.getBegin().isMacroID()) {
6138b4516dSYitzhak Mandelbaum *result_listener << "which starts in a macro";
6238b4516dSYitzhak Mandelbaum return false;
6338b4516dSYitzhak Mandelbaum }
6438b4516dSYitzhak Mandelbaum if (arg.getEnd().isMacroID()) {
6538b4516dSYitzhak Mandelbaum *result_listener << "which ends in a macro";
6638b4516dSYitzhak Mandelbaum return false;
6738b4516dSYitzhak Mandelbaum }
6838b4516dSYitzhak Mandelbaum
69ecfa0b24SGabriel Matute CharSourceRange Range = Lexer::getAsCharRange(
70ecfa0b24SGabriel Matute arg, Context->getSourceManager(), Context->getLangOpts());
71ecfa0b24SGabriel Matute unsigned Begin = Context->getSourceManager().getFileOffset(Range.getBegin());
72ecfa0b24SGabriel Matute unsigned End = Context->getSourceManager().getFileOffset(Range.getEnd());
7338b4516dSYitzhak Mandelbaum
74ecfa0b24SGabriel Matute *result_listener << "which is a " << (arg.isTokenRange() ? "Token" : "Char")
75ecfa0b24SGabriel Matute << " range [" << Begin << "," << End << ")";
7638b4516dSYitzhak Mandelbaum return Begin == R.Begin && End == R.End;
7738b4516dSYitzhak Mandelbaum }
7838b4516dSYitzhak Mandelbaum
AsRange(const SourceManager & SM,llvm::Annotations::Range R)792e97a1e1SYitzhak Mandelbaum static ::testing::Matcher<CharSourceRange> AsRange(const SourceManager &SM,
802e97a1e1SYitzhak Mandelbaum llvm::Annotations::Range R) {
812e97a1e1SYitzhak Mandelbaum return EqualsRange(CharSourceRange::getCharRange(
822e97a1e1SYitzhak Mandelbaum SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(R.Begin),
832e97a1e1SYitzhak Mandelbaum SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(R.End)));
842e97a1e1SYitzhak Mandelbaum }
852e97a1e1SYitzhak Mandelbaum
8638b4516dSYitzhak Mandelbaum // Base class for visitors that expect a single match corresponding to a
8738b4516dSYitzhak Mandelbaum // specific annotated range.
8838b4516dSYitzhak Mandelbaum template <typename T> class AnnotatedCodeVisitor : public TestVisitor<T> {
89ecfa0b24SGabriel Matute protected:
9038b4516dSYitzhak Mandelbaum int MatchCount = 0;
91ecfa0b24SGabriel Matute llvm::Annotations Code;
9238b4516dSYitzhak Mandelbaum
9338b4516dSYitzhak Mandelbaum public:
AnnotatedCodeVisitor()9438b4516dSYitzhak Mandelbaum AnnotatedCodeVisitor() : Code("$r[[]]") {}
95ecfa0b24SGabriel Matute // Helper for tests of `getAssociatedRange`.
VisitDeclHelper(Decl * Decl)9638b4516dSYitzhak Mandelbaum bool VisitDeclHelper(Decl *Decl) {
9738b4516dSYitzhak Mandelbaum // Only consider explicit declarations.
9838b4516dSYitzhak Mandelbaum if (Decl->isImplicit())
9938b4516dSYitzhak Mandelbaum return true;
10038b4516dSYitzhak Mandelbaum
10138b4516dSYitzhak Mandelbaum ++MatchCount;
10238b4516dSYitzhak Mandelbaum EXPECT_THAT(getAssociatedRange(*Decl, *this->Context),
103ecfa0b24SGabriel Matute EqualsAnnotatedRange(this->Context, Code.range("r")))
10438b4516dSYitzhak Mandelbaum << Code.code();
10538b4516dSYitzhak Mandelbaum return true;
10638b4516dSYitzhak Mandelbaum }
10738b4516dSYitzhak Mandelbaum
runOverAnnotated(llvm::StringRef AnnotatedCode,std::vector<std::string> Args={})10838b4516dSYitzhak Mandelbaum bool runOverAnnotated(llvm::StringRef AnnotatedCode,
10938b4516dSYitzhak Mandelbaum std::vector<std::string> Args = {}) {
11038b4516dSYitzhak Mandelbaum Code = llvm::Annotations(AnnotatedCode);
11138b4516dSYitzhak Mandelbaum MatchCount = 0;
11238b4516dSYitzhak Mandelbaum Args.push_back("-std=c++11");
11338b4516dSYitzhak Mandelbaum Args.push_back("-fno-delayed-template-parsing");
11438b4516dSYitzhak Mandelbaum bool result = tooling::runToolOnCodeWithArgs(this->CreateTestAction(),
11538b4516dSYitzhak Mandelbaum Code.code(), Args);
11638b4516dSYitzhak Mandelbaum EXPECT_EQ(MatchCount, 1) << AnnotatedCode;
11738b4516dSYitzhak Mandelbaum return result;
11838b4516dSYitzhak Mandelbaum }
11938b4516dSYitzhak Mandelbaum };
12038b4516dSYitzhak Mandelbaum
TEST(SourceCodeTest,getText)12184f2271aSYitzhak Mandelbaum TEST(SourceCodeTest, getText) {
12284f2271aSYitzhak Mandelbaum CallsVisitor Visitor;
12384f2271aSYitzhak Mandelbaum
12484f2271aSYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
12584f2271aSYitzhak Mandelbaum EXPECT_EQ("foo(x, y)", getText(*CE, *Context));
12684f2271aSYitzhak Mandelbaum };
12784f2271aSYitzhak Mandelbaum Visitor.runOver("void foo(int x, int y) { foo(x, y); }");
12884f2271aSYitzhak Mandelbaum
12984f2271aSYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
13084f2271aSYitzhak Mandelbaum EXPECT_EQ("APPLY(foo, x, y)", getText(*CE, *Context));
13184f2271aSYitzhak Mandelbaum };
13284f2271aSYitzhak Mandelbaum Visitor.runOver("#define APPLY(f, x, y) f(x, y)\n"
13384f2271aSYitzhak Mandelbaum "void foo(int x, int y) { APPLY(foo, x, y); }");
13484f2271aSYitzhak Mandelbaum }
13584f2271aSYitzhak Mandelbaum
TEST(SourceCodeTest,getTextWithMacro)13684f2271aSYitzhak Mandelbaum TEST(SourceCodeTest, getTextWithMacro) {
13784f2271aSYitzhak Mandelbaum CallsVisitor Visitor;
13884f2271aSYitzhak Mandelbaum
13984f2271aSYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
14084f2271aSYitzhak Mandelbaum EXPECT_EQ("F OO", getText(*CE, *Context));
14184f2271aSYitzhak Mandelbaum Expr *P0 = CE->getArg(0);
14284f2271aSYitzhak Mandelbaum Expr *P1 = CE->getArg(1);
14384f2271aSYitzhak Mandelbaum EXPECT_EQ("", getText(*P0, *Context));
14484f2271aSYitzhak Mandelbaum EXPECT_EQ("", getText(*P1, *Context));
14584f2271aSYitzhak Mandelbaum };
14684f2271aSYitzhak Mandelbaum Visitor.runOver("#define F foo(\n"
14784f2271aSYitzhak Mandelbaum "#define OO x, y)\n"
14884f2271aSYitzhak Mandelbaum "void foo(int x, int y) { F OO ; }");
14984f2271aSYitzhak Mandelbaum
15084f2271aSYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
15184f2271aSYitzhak Mandelbaum EXPECT_EQ("", getText(*CE, *Context));
15284f2271aSYitzhak Mandelbaum Expr *P0 = CE->getArg(0);
15384f2271aSYitzhak Mandelbaum Expr *P1 = CE->getArg(1);
15484f2271aSYitzhak Mandelbaum EXPECT_EQ("x", getText(*P0, *Context));
15584f2271aSYitzhak Mandelbaum EXPECT_EQ("y", getText(*P1, *Context));
15684f2271aSYitzhak Mandelbaum };
15784f2271aSYitzhak Mandelbaum Visitor.runOver("#define FOO(x, y) (void)x; (void)y; foo(x, y);\n"
15884f2271aSYitzhak Mandelbaum "void foo(int x, int y) { FOO(x,y) }");
15984f2271aSYitzhak Mandelbaum }
16084f2271aSYitzhak Mandelbaum
TEST(SourceCodeTest,getExtendedText)16184f2271aSYitzhak Mandelbaum TEST(SourceCodeTest, getExtendedText) {
16284f2271aSYitzhak Mandelbaum CallsVisitor Visitor;
16384f2271aSYitzhak Mandelbaum
16484f2271aSYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
16584f2271aSYitzhak Mandelbaum EXPECT_EQ("foo(x, y);",
16684f2271aSYitzhak Mandelbaum getExtendedText(*CE, tok::TokenKind::semi, *Context));
16784f2271aSYitzhak Mandelbaum
16884f2271aSYitzhak Mandelbaum Expr *P0 = CE->getArg(0);
16984f2271aSYitzhak Mandelbaum Expr *P1 = CE->getArg(1);
17084f2271aSYitzhak Mandelbaum EXPECT_EQ("x", getExtendedText(*P0, tok::TokenKind::semi, *Context));
17184f2271aSYitzhak Mandelbaum EXPECT_EQ("x,", getExtendedText(*P0, tok::TokenKind::comma, *Context));
17284f2271aSYitzhak Mandelbaum EXPECT_EQ("y", getExtendedText(*P1, tok::TokenKind::semi, *Context));
17384f2271aSYitzhak Mandelbaum };
17484f2271aSYitzhak Mandelbaum Visitor.runOver("void foo(int x, int y) { foo(x, y); }");
17584f2271aSYitzhak Mandelbaum Visitor.runOver("void foo(int x, int y) { if (true) foo(x, y); }");
17684f2271aSYitzhak Mandelbaum Visitor.runOver("int foo(int x, int y) { if (true) return 3 + foo(x, y); }");
17784f2271aSYitzhak Mandelbaum Visitor.runOver("void foo(int x, int y) { for (foo(x, y);;) ++x; }");
17884f2271aSYitzhak Mandelbaum Visitor.runOver(
17984f2271aSYitzhak Mandelbaum "bool foo(int x, int y) { for (;foo(x, y);) x = 1; return true; }");
18084f2271aSYitzhak Mandelbaum
18184f2271aSYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
18284f2271aSYitzhak Mandelbaum EXPECT_EQ("foo()", getExtendedText(*CE, tok::TokenKind::semi, *Context));
18384f2271aSYitzhak Mandelbaum };
18484f2271aSYitzhak Mandelbaum Visitor.runOver("bool foo() { if (foo()) return true; return false; }");
18584f2271aSYitzhak Mandelbaum Visitor.runOver("void foo() { int x; for (;; foo()) ++x; }");
18684f2271aSYitzhak Mandelbaum Visitor.runOver("int foo() { return foo() + 3; }");
18784f2271aSYitzhak Mandelbaum }
18884f2271aSYitzhak Mandelbaum
TEST(SourceCodeTest,maybeExtendRange_TokenRange)189ecfa0b24SGabriel Matute TEST(SourceCodeTest, maybeExtendRange_TokenRange) {
190ecfa0b24SGabriel Matute struct ExtendTokenRangeVisitor
191ecfa0b24SGabriel Matute : AnnotatedCodeVisitor<ExtendTokenRangeVisitor> {
192ecfa0b24SGabriel Matute bool VisitCallExpr(CallExpr *CE) {
193ecfa0b24SGabriel Matute ++MatchCount;
194ecfa0b24SGabriel Matute EXPECT_THAT(getExtendedRange(*CE, tok::TokenKind::semi, *Context),
195ecfa0b24SGabriel Matute EqualsAnnotatedRange(Context, Code.range("r")));
196ecfa0b24SGabriel Matute return true;
197ecfa0b24SGabriel Matute }
198ecfa0b24SGabriel Matute };
199ecfa0b24SGabriel Matute
200ecfa0b24SGabriel Matute ExtendTokenRangeVisitor Visitor;
201ecfa0b24SGabriel Matute // Extends to include semicolon.
202ecfa0b24SGabriel Matute Visitor.runOverAnnotated("void f(int x, int y) { $r[[f(x, y);]] }");
203ecfa0b24SGabriel Matute // Does not extend to include semicolon.
204ecfa0b24SGabriel Matute Visitor.runOverAnnotated(
205ecfa0b24SGabriel Matute "int f(int x, int y) { if (0) return $r[[f(x, y)]] + 3; }");
206ecfa0b24SGabriel Matute }
207ecfa0b24SGabriel Matute
TEST(SourceCodeTest,maybeExtendRange_CharRange)208ecfa0b24SGabriel Matute TEST(SourceCodeTest, maybeExtendRange_CharRange) {
209ecfa0b24SGabriel Matute struct ExtendCharRangeVisitor : AnnotatedCodeVisitor<ExtendCharRangeVisitor> {
210ecfa0b24SGabriel Matute bool VisitCallExpr(CallExpr *CE) {
211ecfa0b24SGabriel Matute ++MatchCount;
212ecfa0b24SGabriel Matute CharSourceRange Call = Lexer::getAsCharRange(CE->getSourceRange(),
213ecfa0b24SGabriel Matute Context->getSourceManager(),
214ecfa0b24SGabriel Matute Context->getLangOpts());
215ecfa0b24SGabriel Matute EXPECT_THAT(maybeExtendRange(Call, tok::TokenKind::semi, *Context),
216ecfa0b24SGabriel Matute EqualsAnnotatedRange(Context, Code.range("r")));
217ecfa0b24SGabriel Matute return true;
218ecfa0b24SGabriel Matute }
219ecfa0b24SGabriel Matute };
220ecfa0b24SGabriel Matute ExtendCharRangeVisitor Visitor;
221ecfa0b24SGabriel Matute // Extends to include semicolon.
222ecfa0b24SGabriel Matute Visitor.runOverAnnotated("void f(int x, int y) { $r[[f(x, y);]] }");
223ecfa0b24SGabriel Matute // Does not extend to include semicolon.
224ecfa0b24SGabriel Matute Visitor.runOverAnnotated(
225ecfa0b24SGabriel Matute "int f(int x, int y) { if (0) return $r[[f(x, y)]] + 3; }");
226ecfa0b24SGabriel Matute }
227ecfa0b24SGabriel Matute
TEST(SourceCodeTest,getAssociatedRange)22838b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRange) {
22938b4516dSYitzhak Mandelbaum struct VarDeclsVisitor : AnnotatedCodeVisitor<VarDeclsVisitor> {
23038b4516dSYitzhak Mandelbaum bool VisitVarDecl(VarDecl *Decl) { return VisitDeclHelper(Decl); }
23138b4516dSYitzhak Mandelbaum };
23238b4516dSYitzhak Mandelbaum VarDeclsVisitor Visitor;
23338b4516dSYitzhak Mandelbaum
23438b4516dSYitzhak Mandelbaum // Includes semicolon.
23538b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int x = 4;]]");
23638b4516dSYitzhak Mandelbaum
23738b4516dSYitzhak Mandelbaum // Includes newline and semicolon.
23838b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int x = 4;\n]]");
23938b4516dSYitzhak Mandelbaum
24038b4516dSYitzhak Mandelbaum // Includes trailing comments.
24138b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int x = 4; // Comment\n]]");
24238b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int x = 4; /* Comment */\n]]");
24338b4516dSYitzhak Mandelbaum
24438b4516dSYitzhak Mandelbaum // Does *not* include trailing comments when another entity appears between
24538b4516dSYitzhak Mandelbaum // the decl and the comment.
24638b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int x = 4;]] class C {}; // Comment\n");
24738b4516dSYitzhak Mandelbaum
24838b4516dSYitzhak Mandelbaum // Includes attributes.
24938b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated(R"cpp(
25038b4516dSYitzhak Mandelbaum #define ATTR __attribute__((deprecated("message")))
25138b4516dSYitzhak Mandelbaum $r[[ATTR
25238b4516dSYitzhak Mandelbaum int x;]])cpp");
25338b4516dSYitzhak Mandelbaum
25438b4516dSYitzhak Mandelbaum // Includes attributes and comments together.
25538b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated(R"cpp(
25638b4516dSYitzhak Mandelbaum #define ATTR __attribute__((deprecated("message")))
25738b4516dSYitzhak Mandelbaum $r[[ATTR
25838b4516dSYitzhak Mandelbaum // Commment.
25938b4516dSYitzhak Mandelbaum int x;]])cpp");
26038b4516dSYitzhak Mandelbaum }
26138b4516dSYitzhak Mandelbaum
TEST(SourceCodeTest,getAssociatedRangeClasses)26238b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeClasses) {
26338b4516dSYitzhak Mandelbaum struct RecordDeclsVisitor : AnnotatedCodeVisitor<RecordDeclsVisitor> {
26438b4516dSYitzhak Mandelbaum bool VisitRecordDecl(RecordDecl *Decl) { return VisitDeclHelper(Decl); }
26538b4516dSYitzhak Mandelbaum };
26638b4516dSYitzhak Mandelbaum RecordDeclsVisitor Visitor;
26738b4516dSYitzhak Mandelbaum
26838b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[class A;]]");
26938b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[class A {};]]");
27038b4516dSYitzhak Mandelbaum
27138b4516dSYitzhak Mandelbaum // Includes leading template annotation.
27238b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[template <typename T> class A;]]");
27338b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[template <typename T> class A {};]]");
27438b4516dSYitzhak Mandelbaum }
27538b4516dSYitzhak Mandelbaum
TEST(SourceCodeTest,getAssociatedRangeClassTemplateSpecializations)27638b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeClassTemplateSpecializations) {
27738b4516dSYitzhak Mandelbaum struct CXXRecordDeclsVisitor : AnnotatedCodeVisitor<CXXRecordDeclsVisitor> {
27838b4516dSYitzhak Mandelbaum bool VisitCXXRecordDecl(CXXRecordDecl *Decl) {
27938b4516dSYitzhak Mandelbaum return Decl->getTemplateSpecializationKind() !=
28038b4516dSYitzhak Mandelbaum TSK_ExplicitSpecialization ||
28138b4516dSYitzhak Mandelbaum VisitDeclHelper(Decl);
28238b4516dSYitzhak Mandelbaum }
28338b4516dSYitzhak Mandelbaum };
28438b4516dSYitzhak Mandelbaum CXXRecordDeclsVisitor Visitor;
28538b4516dSYitzhak Mandelbaum
28638b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated(R"cpp(
28738b4516dSYitzhak Mandelbaum template <typename T> class A{};
28838b4516dSYitzhak Mandelbaum $r[[template <> class A<int>;]])cpp");
28938b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated(R"cpp(
29038b4516dSYitzhak Mandelbaum template <typename T> class A{};
29138b4516dSYitzhak Mandelbaum $r[[template <> class A<int> {};]])cpp");
29238b4516dSYitzhak Mandelbaum }
29338b4516dSYitzhak Mandelbaum
TEST(SourceCodeTest,getAssociatedRangeFunctions)29438b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeFunctions) {
29538b4516dSYitzhak Mandelbaum struct FunctionDeclsVisitor : AnnotatedCodeVisitor<FunctionDeclsVisitor> {
29638b4516dSYitzhak Mandelbaum bool VisitFunctionDecl(FunctionDecl *Decl) { return VisitDeclHelper(Decl); }
29738b4516dSYitzhak Mandelbaum };
29838b4516dSYitzhak Mandelbaum FunctionDeclsVisitor Visitor;
29938b4516dSYitzhak Mandelbaum
30038b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int f();]]");
30138b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[int f() { return 0; }]]");
30238b4516dSYitzhak Mandelbaum // Includes leading template annotation.
30338b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[template <typename T> int f();]]");
30438b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated("$r[[template <typename T> int f() { return 0; }]]");
30538b4516dSYitzhak Mandelbaum }
30638b4516dSYitzhak Mandelbaum
TEST(SourceCodeTest,getAssociatedRangeMemberTemplates)30738b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeMemberTemplates) {
30838b4516dSYitzhak Mandelbaum struct CXXMethodDeclsVisitor : AnnotatedCodeVisitor<CXXMethodDeclsVisitor> {
30938b4516dSYitzhak Mandelbaum bool VisitCXXMethodDecl(CXXMethodDecl *Decl) {
31038b4516dSYitzhak Mandelbaum // Only consider the definition of the template.
31138b4516dSYitzhak Mandelbaum return !Decl->doesThisDeclarationHaveABody() || VisitDeclHelper(Decl);
31238b4516dSYitzhak Mandelbaum }
31338b4516dSYitzhak Mandelbaum };
31438b4516dSYitzhak Mandelbaum CXXMethodDeclsVisitor Visitor;
31538b4516dSYitzhak Mandelbaum
31638b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated(R"cpp(
31738b4516dSYitzhak Mandelbaum template <typename C>
31838b4516dSYitzhak Mandelbaum struct A { template <typename T> int member(T v); };
31938b4516dSYitzhak Mandelbaum
32038b4516dSYitzhak Mandelbaum $r[[template <typename C>
32138b4516dSYitzhak Mandelbaum template <typename T>
32238b4516dSYitzhak Mandelbaum int A<C>::member(T v) { return 0; }]])cpp");
32338b4516dSYitzhak Mandelbaum }
32438b4516dSYitzhak Mandelbaum
TEST(SourceCodeTest,getAssociatedRangeWithComments)32538b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeWithComments) {
32638b4516dSYitzhak Mandelbaum struct VarDeclsVisitor : AnnotatedCodeVisitor<VarDeclsVisitor> {
32738b4516dSYitzhak Mandelbaum bool VisitVarDecl(VarDecl *Decl) { return VisitDeclHelper(Decl); }
32838b4516dSYitzhak Mandelbaum };
32938b4516dSYitzhak Mandelbaum
33038b4516dSYitzhak Mandelbaum VarDeclsVisitor Visitor;
33138b4516dSYitzhak Mandelbaum auto Visit = [&](llvm::StringRef AnnotatedCode) {
33238b4516dSYitzhak Mandelbaum Visitor.runOverAnnotated(AnnotatedCode, {"-fparse-all-comments"});
33338b4516dSYitzhak Mandelbaum };
33438b4516dSYitzhak Mandelbaum
33538b4516dSYitzhak Mandelbaum // Includes leading comments.
33638b4516dSYitzhak Mandelbaum Visit("$r[[// Comment.\nint x = 4;]]");
33738b4516dSYitzhak Mandelbaum Visit("$r[[// Comment.\nint x = 4;\n]]");
33838b4516dSYitzhak Mandelbaum Visit("$r[[/* Comment.*/\nint x = 4;\n]]");
33938b4516dSYitzhak Mandelbaum // ... even if separated by (extra) horizontal whitespace.
34038b4516dSYitzhak Mandelbaum Visit("$r[[/* Comment.*/ \nint x = 4;\n]]");
34138b4516dSYitzhak Mandelbaum
34238b4516dSYitzhak Mandelbaum // Includes comments even in the presence of trailing whitespace.
34338b4516dSYitzhak Mandelbaum Visit("$r[[// Comment.\nint x = 4;]] ");
34438b4516dSYitzhak Mandelbaum
34538b4516dSYitzhak Mandelbaum // Includes comments when the declaration is followed by the beginning or end
34638b4516dSYitzhak Mandelbaum // of a compound statement.
34738b4516dSYitzhak Mandelbaum Visit(R"cpp(
34838b4516dSYitzhak Mandelbaum void foo() {
34938b4516dSYitzhak Mandelbaum $r[[/* C */
35038b4516dSYitzhak Mandelbaum int x = 4;
35138b4516dSYitzhak Mandelbaum ]]};)cpp");
35238b4516dSYitzhak Mandelbaum Visit(R"cpp(
35338b4516dSYitzhak Mandelbaum void foo() {
35438b4516dSYitzhak Mandelbaum $r[[/* C */
35538b4516dSYitzhak Mandelbaum int x = 4;
35638b4516dSYitzhak Mandelbaum ]]{ class Foo {}; }
35738b4516dSYitzhak Mandelbaum })cpp");
35838b4516dSYitzhak Mandelbaum
35938b4516dSYitzhak Mandelbaum // Includes comments inside macros (when decl is in the same macro).
36038b4516dSYitzhak Mandelbaum Visit(R"cpp(
36138b4516dSYitzhak Mandelbaum #define DECL /* Comment */ int x
36238b4516dSYitzhak Mandelbaum $r[[DECL;]])cpp");
36338b4516dSYitzhak Mandelbaum
36438b4516dSYitzhak Mandelbaum // Does not include comments when only the decl or the comment come from a
36538b4516dSYitzhak Mandelbaum // macro.
36638b4516dSYitzhak Mandelbaum // FIXME: Change code to allow this.
36738b4516dSYitzhak Mandelbaum Visit(R"cpp(
36838b4516dSYitzhak Mandelbaum #define DECL int x
36938b4516dSYitzhak Mandelbaum // Comment
37038b4516dSYitzhak Mandelbaum $r[[DECL;]])cpp");
37138b4516dSYitzhak Mandelbaum Visit(R"cpp(
37238b4516dSYitzhak Mandelbaum #define COMMENT /* Comment */
37338b4516dSYitzhak Mandelbaum COMMENT
37438b4516dSYitzhak Mandelbaum $r[[int x;]])cpp");
37538b4516dSYitzhak Mandelbaum
37638b4516dSYitzhak Mandelbaum // Includes multi-line comments.
37738b4516dSYitzhak Mandelbaum Visit(R"cpp(
37838b4516dSYitzhak Mandelbaum $r[[/* multi
37938b4516dSYitzhak Mandelbaum * line
38038b4516dSYitzhak Mandelbaum * comment
38138b4516dSYitzhak Mandelbaum */
38238b4516dSYitzhak Mandelbaum int x;]])cpp");
38338b4516dSYitzhak Mandelbaum Visit(R"cpp(
38438b4516dSYitzhak Mandelbaum $r[[// multi
38538b4516dSYitzhak Mandelbaum // line
38638b4516dSYitzhak Mandelbaum // comment
38738b4516dSYitzhak Mandelbaum int x;]])cpp");
38838b4516dSYitzhak Mandelbaum
38938b4516dSYitzhak Mandelbaum // Does not include comments separated by multiple empty lines.
39038b4516dSYitzhak Mandelbaum Visit("// Comment.\n\n\n$r[[int x = 4;\n]]");
39138b4516dSYitzhak Mandelbaum Visit("/* Comment.*/\n\n\n$r[[int x = 4;\n]]");
39238b4516dSYitzhak Mandelbaum
39338b4516dSYitzhak Mandelbaum // Does not include comments before a *series* of declarations.
39438b4516dSYitzhak Mandelbaum Visit(R"cpp(
39538b4516dSYitzhak Mandelbaum // Comment.
39638b4516dSYitzhak Mandelbaum $r[[int x = 4;
39738b4516dSYitzhak Mandelbaum ]]class foo {};)cpp");
39838b4516dSYitzhak Mandelbaum
39938b4516dSYitzhak Mandelbaum // Does not include IfThisThenThat comments
40038b4516dSYitzhak Mandelbaum Visit("// LINT.IfChange.\n$r[[int x = 4;]]");
40138b4516dSYitzhak Mandelbaum Visit("// LINT.ThenChange.\n$r[[int x = 4;]]");
40238b4516dSYitzhak Mandelbaum
40338b4516dSYitzhak Mandelbaum // Includes attributes.
40438b4516dSYitzhak Mandelbaum Visit(R"cpp(
40538b4516dSYitzhak Mandelbaum #define ATTR __attribute__((deprecated("message")))
40638b4516dSYitzhak Mandelbaum $r[[ATTR
40738b4516dSYitzhak Mandelbaum int x;]])cpp");
40838b4516dSYitzhak Mandelbaum
40938b4516dSYitzhak Mandelbaum // Includes attributes and comments together.
41038b4516dSYitzhak Mandelbaum Visit(R"cpp(
41138b4516dSYitzhak Mandelbaum #define ATTR __attribute__((deprecated("message")))
41238b4516dSYitzhak Mandelbaum $r[[ATTR
41338b4516dSYitzhak Mandelbaum // Commment.
41438b4516dSYitzhak Mandelbaum int x;]])cpp");
41538b4516dSYitzhak Mandelbaum }
41638b4516dSYitzhak Mandelbaum
TEST(SourceCodeTest,getAssociatedRangeInvalidForPartialExpansions)41738b4516dSYitzhak Mandelbaum TEST(SourceCodeTest, getAssociatedRangeInvalidForPartialExpansions) {
41838b4516dSYitzhak Mandelbaum struct FailingVarDeclsVisitor : TestVisitor<FailingVarDeclsVisitor> {
41938b4516dSYitzhak Mandelbaum FailingVarDeclsVisitor() {}
42038b4516dSYitzhak Mandelbaum bool VisitVarDecl(VarDecl *Decl) {
42138b4516dSYitzhak Mandelbaum EXPECT_TRUE(getAssociatedRange(*Decl, *Context).isInvalid());
42238b4516dSYitzhak Mandelbaum return true;
42338b4516dSYitzhak Mandelbaum }
42438b4516dSYitzhak Mandelbaum };
42538b4516dSYitzhak Mandelbaum
42638b4516dSYitzhak Mandelbaum FailingVarDeclsVisitor Visitor;
42738b4516dSYitzhak Mandelbaum // Should fail because it only includes a part of the expansion.
42838b4516dSYitzhak Mandelbaum std::string Code = R"cpp(
42938b4516dSYitzhak Mandelbaum #define DECL class foo { }; int x
43038b4516dSYitzhak Mandelbaum DECL;)cpp";
43138b4516dSYitzhak Mandelbaum Visitor.runOver(Code);
43238b4516dSYitzhak Mandelbaum }
43338b4516dSYitzhak Mandelbaum
TEST(SourceCodeTest,EditRangeWithMacroExpansionsShouldSucceed)4342e97a1e1SYitzhak Mandelbaum TEST(SourceCodeTest, EditRangeWithMacroExpansionsShouldSucceed) {
4352e97a1e1SYitzhak Mandelbaum // The call expression, whose range we are extracting, includes two macro
4362e97a1e1SYitzhak Mandelbaum // expansions.
4372e97a1e1SYitzhak Mandelbaum llvm::Annotations Code(R"cpp(
4382e97a1e1SYitzhak Mandelbaum #define M(a) a * 13
4392e97a1e1SYitzhak Mandelbaum int foo(int x, int y);
4402e97a1e1SYitzhak Mandelbaum int a = $r[[foo(M(1), M(2))]];
4412e97a1e1SYitzhak Mandelbaum )cpp");
4422e97a1e1SYitzhak Mandelbaum
4432e97a1e1SYitzhak Mandelbaum CallsVisitor Visitor;
4442e97a1e1SYitzhak Mandelbaum
4452e97a1e1SYitzhak Mandelbaum Visitor.OnCall = [&Code](CallExpr *CE, ASTContext *Context) {
4462e97a1e1SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(CE->getSourceRange());
4472e97a1e1SYitzhak Mandelbaum EXPECT_THAT(getRangeForEdit(Range, *Context),
4482e97a1e1SYitzhak Mandelbaum ValueIs(AsRange(Context->getSourceManager(), Code.range("r"))));
4492e97a1e1SYitzhak Mandelbaum };
4502e97a1e1SYitzhak Mandelbaum Visitor.runOver(Code.code());
4512e97a1e1SYitzhak Mandelbaum }
4522e97a1e1SYitzhak Mandelbaum
TEST(SourceCodeTest,EditWholeMacroExpansionShouldSucceed)4532e97a1e1SYitzhak Mandelbaum TEST(SourceCodeTest, EditWholeMacroExpansionShouldSucceed) {
4542e97a1e1SYitzhak Mandelbaum llvm::Annotations Code(R"cpp(
4552e97a1e1SYitzhak Mandelbaum #define FOO 10
4562e97a1e1SYitzhak Mandelbaum int a = $r[[FOO]];
4572e97a1e1SYitzhak Mandelbaum )cpp");
4582e97a1e1SYitzhak Mandelbaum
4592e97a1e1SYitzhak Mandelbaum IntLitVisitor Visitor;
4602e97a1e1SYitzhak Mandelbaum Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) {
4612e97a1e1SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
4622e97a1e1SYitzhak Mandelbaum EXPECT_THAT(getRangeForEdit(Range, *Context),
4632e97a1e1SYitzhak Mandelbaum ValueIs(AsRange(Context->getSourceManager(), Code.range("r"))));
4642e97a1e1SYitzhak Mandelbaum };
4652e97a1e1SYitzhak Mandelbaum Visitor.runOver(Code.code());
4662e97a1e1SYitzhak Mandelbaum }
4672e97a1e1SYitzhak Mandelbaum
TEST(SourceCodeTest,EditPartialMacroExpansionShouldFail)4682e97a1e1SYitzhak Mandelbaum TEST(SourceCodeTest, EditPartialMacroExpansionShouldFail) {
4692e97a1e1SYitzhak Mandelbaum std::string Code = R"cpp(
4702e97a1e1SYitzhak Mandelbaum #define BAR 10+
4712e97a1e1SYitzhak Mandelbaum int c = BAR 3.0;
4722e97a1e1SYitzhak Mandelbaum )cpp";
4732e97a1e1SYitzhak Mandelbaum
4742e97a1e1SYitzhak Mandelbaum IntLitVisitor Visitor;
4752e97a1e1SYitzhak Mandelbaum Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {
4762e97a1e1SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
477*b8df4093SKazu Hirata EXPECT_FALSE(getRangeForEdit(Range, *Context));
4782e97a1e1SYitzhak Mandelbaum };
4792e97a1e1SYitzhak Mandelbaum Visitor.runOver(Code);
4802e97a1e1SYitzhak Mandelbaum }
4812e97a1e1SYitzhak Mandelbaum
TEST(SourceCodeTest,EditWholeMacroArgShouldSucceed)4822e97a1e1SYitzhak Mandelbaum TEST(SourceCodeTest, EditWholeMacroArgShouldSucceed) {
4832e97a1e1SYitzhak Mandelbaum llvm::Annotations Code(R"cpp(
4842e97a1e1SYitzhak Mandelbaum #define FOO(a) a + 7.0;
4852e97a1e1SYitzhak Mandelbaum int a = FOO($r[[10]]);
4862e97a1e1SYitzhak Mandelbaum )cpp");
4872e97a1e1SYitzhak Mandelbaum
4882e97a1e1SYitzhak Mandelbaum IntLitVisitor Visitor;
4892e97a1e1SYitzhak Mandelbaum Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) {
4902e97a1e1SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
4912e97a1e1SYitzhak Mandelbaum EXPECT_THAT(getRangeForEdit(Range, *Context),
4922e97a1e1SYitzhak Mandelbaum ValueIs(AsRange(Context->getSourceManager(), Code.range("r"))));
4932e97a1e1SYitzhak Mandelbaum };
4942e97a1e1SYitzhak Mandelbaum Visitor.runOver(Code.code());
4952e97a1e1SYitzhak Mandelbaum }
4962e97a1e1SYitzhak Mandelbaum
TEST(SourceCodeTest,EditPartialMacroArgShouldSucceed)4972e97a1e1SYitzhak Mandelbaum TEST(SourceCodeTest, EditPartialMacroArgShouldSucceed) {
4982e97a1e1SYitzhak Mandelbaum llvm::Annotations Code(R"cpp(
4992e97a1e1SYitzhak Mandelbaum #define FOO(a) a + 7.0;
5002e97a1e1SYitzhak Mandelbaum int a = FOO($r[[10]] + 10.0);
5012e97a1e1SYitzhak Mandelbaum )cpp");
5022e97a1e1SYitzhak Mandelbaum
5032e97a1e1SYitzhak Mandelbaum IntLitVisitor Visitor;
5042e97a1e1SYitzhak Mandelbaum Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) {
5052e97a1e1SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
5062e97a1e1SYitzhak Mandelbaum EXPECT_THAT(getRangeForEdit(Range, *Context),
5072e97a1e1SYitzhak Mandelbaum ValueIs(AsRange(Context->getSourceManager(), Code.range("r"))));
5082e97a1e1SYitzhak Mandelbaum };
5092e97a1e1SYitzhak Mandelbaum Visitor.runOver(Code.code());
5102e97a1e1SYitzhak Mandelbaum }
5112e97a1e1SYitzhak Mandelbaum
TEST(SourceCodeTest,EditRangeWithMacroExpansionsIsValid)512b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, EditRangeWithMacroExpansionsIsValid) {
513b9d2bf38SYitzhak Mandelbaum // The call expression, whose range we are extracting, includes two macro
514b9d2bf38SYitzhak Mandelbaum // expansions.
515b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = R"cpp(
516b9d2bf38SYitzhak Mandelbaum #define M(a) a * 13
517b9d2bf38SYitzhak Mandelbaum int foo(int x, int y);
518b9d2bf38SYitzhak Mandelbaum int a = foo(M(1), M(2));
519b9d2bf38SYitzhak Mandelbaum )cpp";
520b9d2bf38SYitzhak Mandelbaum
521b9d2bf38SYitzhak Mandelbaum CallsVisitor Visitor;
522b9d2bf38SYitzhak Mandelbaum
523b9d2bf38SYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {
524b9d2bf38SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(CE->getSourceRange());
525b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()),
526b9d2bf38SYitzhak Mandelbaum Succeeded());
527b9d2bf38SYitzhak Mandelbaum };
528b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code);
529b9d2bf38SYitzhak Mandelbaum }
530b9d2bf38SYitzhak Mandelbaum
TEST(SourceCodeTest,SpellingRangeOfMacroArgIsValid)531b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, SpellingRangeOfMacroArgIsValid) {
532b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = R"cpp(
533b9d2bf38SYitzhak Mandelbaum #define FOO(a) a + 7.0;
534b9d2bf38SYitzhak Mandelbaum int a = FOO(10);
535b9d2bf38SYitzhak Mandelbaum )cpp";
536b9d2bf38SYitzhak Mandelbaum
537b9d2bf38SYitzhak Mandelbaum IntLitVisitor Visitor;
538b9d2bf38SYitzhak Mandelbaum Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {
539b9d2bf38SYitzhak Mandelbaum SourceLocation ArgLoc =
540b9d2bf38SYitzhak Mandelbaum Context->getSourceManager().getSpellingLoc(Expr->getBeginLoc());
541b9d2bf38SYitzhak Mandelbaum // The integer literal is a single token.
542b9d2bf38SYitzhak Mandelbaum auto ArgRange = CharSourceRange::getTokenRange(ArgLoc);
543b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(validateEditRange(ArgRange, Context->getSourceManager()),
544b9d2bf38SYitzhak Mandelbaum Succeeded());
545b9d2bf38SYitzhak Mandelbaum };
546b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code);
547b9d2bf38SYitzhak Mandelbaum }
548b9d2bf38SYitzhak Mandelbaum
TEST(SourceCodeTest,InvalidEditRangeIsInvalid)549b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, InvalidEditRangeIsInvalid) {
550b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = "int c = 10;";
551b9d2bf38SYitzhak Mandelbaum
552b9d2bf38SYitzhak Mandelbaum // We use the visitor just to get a valid context.
553b9d2bf38SYitzhak Mandelbaum IntLitVisitor Visitor;
554b9d2bf38SYitzhak Mandelbaum Visitor.OnIntLit = [](IntegerLiteral *, ASTContext *Context) {
555b9d2bf38SYitzhak Mandelbaum CharSourceRange Invalid;
556b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(validateEditRange(Invalid, Context->getSourceManager()),
557b9d2bf38SYitzhak Mandelbaum Failed());
558b9d2bf38SYitzhak Mandelbaum };
559b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code);
560b9d2bf38SYitzhak Mandelbaum }
561b9d2bf38SYitzhak Mandelbaum
TEST(SourceCodeTest,InvertedEditRangeIsInvalid)562b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, InvertedEditRangeIsInvalid) {
563b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = R"cpp(
564b9d2bf38SYitzhak Mandelbaum int foo(int x);
565b9d2bf38SYitzhak Mandelbaum int a = foo(2);
566b9d2bf38SYitzhak Mandelbaum )cpp";
567b9d2bf38SYitzhak Mandelbaum
568b9d2bf38SYitzhak Mandelbaum CallsVisitor Visitor;
569b9d2bf38SYitzhak Mandelbaum Visitor.OnCall = [](CallExpr *Expr, ASTContext *Context) {
570b9d2bf38SYitzhak Mandelbaum auto InvertedRange = CharSourceRange::getTokenRange(
571b9d2bf38SYitzhak Mandelbaum SourceRange(Expr->getEndLoc(), Expr->getBeginLoc()));
572b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(
573b9d2bf38SYitzhak Mandelbaum validateEditRange(InvertedRange, Context->getSourceManager()),
574b9d2bf38SYitzhak Mandelbaum Failed());
575b9d2bf38SYitzhak Mandelbaum };
576b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code);
577b9d2bf38SYitzhak Mandelbaum }
578b9d2bf38SYitzhak Mandelbaum
TEST(SourceCodeTest,MacroArgIsInvalid)579b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, MacroArgIsInvalid) {
580b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = R"cpp(
581b9d2bf38SYitzhak Mandelbaum #define FOO(a) a + 7.0;
582b9d2bf38SYitzhak Mandelbaum int a = FOO(10);
583b9d2bf38SYitzhak Mandelbaum )cpp";
584b9d2bf38SYitzhak Mandelbaum
585b9d2bf38SYitzhak Mandelbaum IntLitVisitor Visitor;
586b9d2bf38SYitzhak Mandelbaum Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {
587b9d2bf38SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
588b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()),
589b9d2bf38SYitzhak Mandelbaum Failed());
590b9d2bf38SYitzhak Mandelbaum };
591b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code);
592b9d2bf38SYitzhak Mandelbaum }
593b9d2bf38SYitzhak Mandelbaum
TEST(SourceCodeTest,EditWholeMacroExpansionIsInvalid)594b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, EditWholeMacroExpansionIsInvalid) {
595b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = R"cpp(
596b9d2bf38SYitzhak Mandelbaum #define FOO 10
597b9d2bf38SYitzhak Mandelbaum int a = FOO;
598b9d2bf38SYitzhak Mandelbaum )cpp";
599b9d2bf38SYitzhak Mandelbaum
600b9d2bf38SYitzhak Mandelbaum IntLitVisitor Visitor;
601b9d2bf38SYitzhak Mandelbaum Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {
602b9d2bf38SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
603b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()),
604b9d2bf38SYitzhak Mandelbaum Failed());
605b9d2bf38SYitzhak Mandelbaum
606b9d2bf38SYitzhak Mandelbaum };
607b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code);
608b9d2bf38SYitzhak Mandelbaum }
609b9d2bf38SYitzhak Mandelbaum
TEST(SourceCodeTest,EditPartialMacroExpansionIsInvalid)610b9d2bf38SYitzhak Mandelbaum TEST(SourceCodeTest, EditPartialMacroExpansionIsInvalid) {
611b9d2bf38SYitzhak Mandelbaum llvm::StringRef Code = R"cpp(
612b9d2bf38SYitzhak Mandelbaum #define BAR 10+
613b9d2bf38SYitzhak Mandelbaum int c = BAR 3.0;
614b9d2bf38SYitzhak Mandelbaum )cpp";
615b9d2bf38SYitzhak Mandelbaum
616b9d2bf38SYitzhak Mandelbaum IntLitVisitor Visitor;
617b9d2bf38SYitzhak Mandelbaum Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {
618b9d2bf38SYitzhak Mandelbaum auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());
619b9d2bf38SYitzhak Mandelbaum EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()),
620b9d2bf38SYitzhak Mandelbaum Failed());
621b9d2bf38SYitzhak Mandelbaum };
622b9d2bf38SYitzhak Mandelbaum Visitor.runOver(Code);
623b9d2bf38SYitzhak Mandelbaum }
6246e519910SBalázs Kéri
TEST(SourceCodeTest,GetCallReturnType_Dependent)6256e519910SBalázs Kéri TEST(SourceCodeTest, GetCallReturnType_Dependent) {
6266e519910SBalázs Kéri llvm::Annotations Code{R"cpp(
6276e519910SBalázs Kéri template<class T, class F>
6286e519910SBalázs Kéri void templ(const T& t, F f) {}
6296e519910SBalázs Kéri
6306e519910SBalázs Kéri template<class T, class F>
6316e519910SBalázs Kéri void templ1(const T& t, F f) {
6326e519910SBalázs Kéri $test1[[f(t)]];
6336e519910SBalázs Kéri }
6346e519910SBalázs Kéri
6356e519910SBalázs Kéri int f_overload(int) { return 1; }
6366e519910SBalázs Kéri int f_overload(double) { return 2; }
6376e519910SBalázs Kéri
6386e519910SBalázs Kéri void f1() {
6396e519910SBalázs Kéri int i = 0;
6406e519910SBalázs Kéri templ(i, [](const auto &p) {
6416e519910SBalázs Kéri $test2[[f_overload(p)]];
6426e519910SBalázs Kéri });
6436e519910SBalázs Kéri }
6446e519910SBalázs Kéri
6456e519910SBalázs Kéri struct A {
6466e519910SBalázs Kéri void f_overload(int);
6476e519910SBalázs Kéri void f_overload(double);
6486e519910SBalázs Kéri };
6496e519910SBalázs Kéri
6506e519910SBalázs Kéri void f2() {
6516e519910SBalázs Kéri int i = 0;
6526e519910SBalázs Kéri templ(i, [](const auto &p) {
6536e519910SBalázs Kéri A a;
6546e519910SBalázs Kéri $test3[[a.f_overload(p)]];
6556e519910SBalázs Kéri });
6566e519910SBalázs Kéri }
6576e519910SBalázs Kéri )cpp"};
6586e519910SBalázs Kéri
6596e519910SBalázs Kéri llvm::Annotations::Range R1 = Code.range("test1");
6606e519910SBalázs Kéri llvm::Annotations::Range R2 = Code.range("test2");
6616e519910SBalázs Kéri llvm::Annotations::Range R3 = Code.range("test3");
6626e519910SBalázs Kéri
6636e519910SBalázs Kéri CallsVisitor Visitor;
6646e519910SBalázs Kéri Visitor.OnCall = [&R1, &R2, &R3](CallExpr *Expr, ASTContext *Context) {
6656e519910SBalázs Kéri unsigned Begin = Context->getSourceManager().getFileOffset(
6666e519910SBalázs Kéri Expr->getSourceRange().getBegin());
6676e519910SBalázs Kéri unsigned End = Context->getSourceManager().getFileOffset(
6686e519910SBalázs Kéri Expr->getSourceRange().getEnd());
6696e519910SBalázs Kéri llvm::Annotations::Range R{Begin, End + 1};
6706e519910SBalázs Kéri
6716e519910SBalázs Kéri QualType CalleeType = Expr->getCallee()->getType();
6726e519910SBalázs Kéri if (R == R1) {
6736e519910SBalázs Kéri ASSERT_TRUE(CalleeType->isDependentType());
6746e519910SBalázs Kéri EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy);
6756e519910SBalázs Kéri } else if (R == R2) {
6766e519910SBalázs Kéri ASSERT_FALSE(CalleeType->isDependentType());
6776e519910SBalázs Kéri ASSERT_TRUE(CalleeType->isSpecificPlaceholderType(BuiltinType::Overload));
6786e519910SBalázs Kéri ASSERT_TRUE(isa<UnresolvedLookupExpr>(Expr->getCallee()));
6796e519910SBalázs Kéri EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy);
6806e519910SBalázs Kéri } else if (R == R3) {
6816e519910SBalázs Kéri ASSERT_FALSE(CalleeType->isDependentType());
6826e519910SBalázs Kéri ASSERT_TRUE(
6836e519910SBalázs Kéri CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember));
6846e519910SBalázs Kéri ASSERT_TRUE(isa<UnresolvedMemberExpr>(Expr->getCallee()));
6856e519910SBalázs Kéri EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy);
6866e519910SBalázs Kéri }
6876e519910SBalázs Kéri };
6886e519910SBalázs Kéri Visitor.runOver(Code.code(), CallsVisitor::Lang_CXX14);
6896e519910SBalázs Kéri }
6906e519910SBalázs Kéri
69184f2271aSYitzhak Mandelbaum } // end anonymous namespace
692