803 lines · cpp
1//===- unittest/Tooling/SourceCodeTest.cpp --------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Tooling/Transformer/SourceCode.h"10#include "TestVisitor.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12#include "clang/Basic/Diagnostic.h"13#include "clang/Basic/SourceLocation.h"14#include "clang/Lex/Lexer.h"15#include "llvm/Testing/Annotations/Annotations.h"16#include "llvm/Testing/Support/Error.h"17#include "llvm/Testing/Support/SupportHelpers.h"18#include <gmock/gmock.h>19#include <gtest/gtest.h>20 21using namespace clang;22using namespace clang::ast_matchers;23 24using llvm::Failed;25using llvm::Succeeded;26using llvm::ValueIs;27using testing::Optional;28using tooling::getAssociatedRange;29using tooling::getExtendedRange;30using tooling::getExtendedText;31using tooling::getFileRangeForEdit;32using tooling::getText;33using tooling::maybeExtendRange;34using tooling::validateEditRange;35 36namespace {37 38struct IntLitVisitor : TestVisitor {39 bool VisitIntegerLiteral(IntegerLiteral *Expr) override {40 OnIntLit(Expr, Context);41 return true;42 }43 44 std::function<void(IntegerLiteral *, ASTContext *Context)> OnIntLit;45};46 47struct CallsVisitor : TestVisitor {48 bool VisitCallExpr(CallExpr *Expr) override {49 OnCall(Expr, Context);50 return true;51 }52 53 std::function<void(CallExpr *, ASTContext *Context)> OnCall;54};55 56struct TypeLocVisitor : TestVisitor {57 bool VisitTypeLoc(TypeLoc TL) override {58 OnTypeLoc(TL, Context);59 return true;60 }61 62 std::function<void(TypeLoc, ASTContext *Context)> OnTypeLoc;63};64 65// Equality matcher for `clang::CharSourceRange`, which lacks `operator==`.66MATCHER_P(EqualsRange, R, "") {67 return arg.isTokenRange() == R.isTokenRange() &&68 arg.getBegin() == R.getBegin() && arg.getEnd() == R.getEnd();69}70 71MATCHER_P2(EqualsAnnotatedRange, Context, R, "") {72 if (arg.getBegin().isMacroID()) {73 *result_listener << "which starts in a macro";74 return false;75 }76 if (arg.getEnd().isMacroID()) {77 *result_listener << "which ends in a macro";78 return false;79 }80 81 CharSourceRange Range = Lexer::getAsCharRange(82 arg, Context->getSourceManager(), Context->getLangOpts());83 unsigned Begin = Context->getSourceManager().getFileOffset(Range.getBegin());84 unsigned End = Context->getSourceManager().getFileOffset(Range.getEnd());85 86 *result_listener << "which is a " << (arg.isTokenRange() ? "Token" : "Char")87 << " range [" << Begin << "," << End << ")";88 return Begin == R.Begin && End == R.End;89}90 91static ::testing::Matcher<CharSourceRange> AsRange(const SourceManager &SM,92 llvm::Annotations::Range R) {93 return EqualsRange(CharSourceRange::getCharRange(94 SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(R.Begin),95 SM.getLocForStartOfFile(SM.getMainFileID()).getLocWithOffset(R.End)));96}97 98// Base class for visitors that expect a single match corresponding to a99// specific annotated range.100class AnnotatedCodeVisitor : public TestVisitor {101protected:102 int MatchCount = 0;103 llvm::Annotations Code;104 105public:106 AnnotatedCodeVisitor() : Code("$r[[]]") {}107 // Helper for tests of `getAssociatedRange`.108 bool VisitDeclHelper(Decl *Decl) {109 // Only consider explicit declarations.110 if (Decl->isImplicit())111 return true;112 113 ++MatchCount;114 EXPECT_THAT(getAssociatedRange(*Decl, *this->Context),115 EqualsAnnotatedRange(this->Context, Code.range("r")))116 << Code.code();117 return true;118 }119 120 bool runOverAnnotated(llvm::StringRef AnnotatedCode,121 std::vector<std::string> Args = {}) {122 Code = llvm::Annotations(AnnotatedCode);123 MatchCount = 0;124 Args.push_back("-std=c++11");125 Args.push_back("-fno-delayed-template-parsing");126 bool result = tooling::runToolOnCodeWithArgs(this->CreateTestAction(),127 Code.code(), Args);128 EXPECT_EQ(MatchCount, 1) << AnnotatedCode;129 return result;130 }131};132 133TEST(SourceCodeTest, getText) {134 CallsVisitor Visitor;135 136 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {137 EXPECT_EQ("foo(x, y)", getText(*CE, *Context));138 };139 Visitor.runOver("void foo(int x, int y) { foo(x, y); }");140 141 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {142 EXPECT_EQ("APPLY(foo, x, y)", getText(*CE, *Context));143 };144 Visitor.runOver("#define APPLY(f, x, y) f(x, y)\n"145 "void foo(int x, int y) { APPLY(foo, x, y); }");146}147 148TEST(SourceCodeTest, getTextWithMacro) {149 CallsVisitor Visitor;150 151 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {152 EXPECT_EQ("F OO", getText(*CE, *Context));153 Expr *P0 = CE->getArg(0);154 Expr *P1 = CE->getArg(1);155 EXPECT_EQ("", getText(*P0, *Context));156 EXPECT_EQ("", getText(*P1, *Context));157 };158 Visitor.runOver("#define F foo(\n"159 "#define OO x, y)\n"160 "void foo(int x, int y) { F OO ; }");161 162 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {163 EXPECT_EQ("", getText(*CE, *Context));164 Expr *P0 = CE->getArg(0);165 Expr *P1 = CE->getArg(1);166 EXPECT_EQ("x", getText(*P0, *Context));167 EXPECT_EQ("y", getText(*P1, *Context));168 };169 Visitor.runOver("#define FOO(x, y) (void)x; (void)y; foo(x, y);\n"170 "void foo(int x, int y) { FOO(x,y) }");171}172 173TEST(SourceCodeTest, getExtendedText) {174 CallsVisitor Visitor;175 176 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {177 EXPECT_EQ("foo(x, y);",178 getExtendedText(*CE, tok::TokenKind::semi, *Context));179 180 Expr *P0 = CE->getArg(0);181 Expr *P1 = CE->getArg(1);182 EXPECT_EQ("x", getExtendedText(*P0, tok::TokenKind::semi, *Context));183 EXPECT_EQ("x,", getExtendedText(*P0, tok::TokenKind::comma, *Context));184 EXPECT_EQ("y", getExtendedText(*P1, tok::TokenKind::semi, *Context));185 };186 Visitor.runOver("void foo(int x, int y) { foo(x, y); }");187 Visitor.runOver("void foo(int x, int y) { if (true) foo(x, y); }");188 Visitor.runOver("int foo(int x, int y) { if (true) return 3 + foo(x, y); }");189 Visitor.runOver("void foo(int x, int y) { for (foo(x, y);;) ++x; }");190 Visitor.runOver(191 "bool foo(int x, int y) { for (;foo(x, y);) x = 1; return true; }");192 193 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {194 EXPECT_EQ("foo()", getExtendedText(*CE, tok::TokenKind::semi, *Context));195 };196 Visitor.runOver("bool foo() { if (foo()) return true; return false; }");197 Visitor.runOver("void foo() { int x; for (;; foo()) ++x; }");198 Visitor.runOver("int foo() { return foo() + 3; }");199}200 201TEST(SourceCodeTest, maybeExtendRange_TokenRange) {202 struct ExtendTokenRangeVisitor : AnnotatedCodeVisitor {203 bool VisitCallExpr(CallExpr *CE) override {204 ++MatchCount;205 EXPECT_THAT(getExtendedRange(*CE, tok::TokenKind::semi, *Context),206 EqualsAnnotatedRange(Context, Code.range("r")));207 return true;208 }209 };210 211 ExtendTokenRangeVisitor Visitor;212 // Extends to include semicolon.213 Visitor.runOverAnnotated("void f(int x, int y) { $r[[f(x, y);]] }");214 // Does not extend to include semicolon.215 Visitor.runOverAnnotated(216 "int f(int x, int y) { if (0) return $r[[f(x, y)]] + 3; }");217}218 219TEST(SourceCodeTest, maybeExtendRange_CharRange) {220 struct ExtendCharRangeVisitor : AnnotatedCodeVisitor {221 bool VisitCallExpr(CallExpr *CE) override {222 ++MatchCount;223 CharSourceRange Call = Lexer::getAsCharRange(CE->getSourceRange(),224 Context->getSourceManager(),225 Context->getLangOpts());226 EXPECT_THAT(maybeExtendRange(Call, tok::TokenKind::semi, *Context),227 EqualsAnnotatedRange(Context, Code.range("r")));228 return true;229 }230 };231 ExtendCharRangeVisitor Visitor;232 // Extends to include semicolon.233 Visitor.runOverAnnotated("void f(int x, int y) { $r[[f(x, y);]] }");234 // Does not extend to include semicolon.235 Visitor.runOverAnnotated(236 "int f(int x, int y) { if (0) return $r[[f(x, y)]] + 3; }");237}238 239TEST(SourceCodeTest, getAssociatedRange) {240 struct VarDeclsVisitor : AnnotatedCodeVisitor {241 bool VisitVarDecl(VarDecl *Decl) override { return VisitDeclHelper(Decl); }242 };243 VarDeclsVisitor Visitor;244 245 // Includes semicolon.246 Visitor.runOverAnnotated("$r[[int x = 4;]]");247 248 // Includes newline and semicolon.249 Visitor.runOverAnnotated("$r[[int x = 4;\n]]");250 251 // Includes trailing comments.252 Visitor.runOverAnnotated("$r[[int x = 4; // Comment\n]]");253 Visitor.runOverAnnotated("$r[[int x = 4; /* Comment */\n]]");254 255 // Does *not* include trailing comments when another entity appears between256 // the decl and the comment.257 Visitor.runOverAnnotated("$r[[int x = 4;]] class C {}; // Comment\n");258 259 // Includes attributes.260 Visitor.runOverAnnotated(R"cpp(261 $r[[__attribute__((deprecated("message")))262 int x;]])cpp");263 264 // Includes attributes and comments together.265 Visitor.runOverAnnotated(R"cpp(266 $r[[__attribute__((deprecated("message")))267 // Comment.268 int x;]])cpp");269 270 // Includes attributes through macro expansion.271 Visitor.runOverAnnotated(R"cpp(272 #define MACRO_EXPANSION __attribute__((deprecated("message")))273 $r[[MACRO_EXPANSION274 int x;]])cpp");275 276 // Includes attributes through macro expansion with comments.277 Visitor.runOverAnnotated(R"cpp(278 #define MACRO_EXPANSION __attribute__((deprecated("message")))279 $r[[MACRO_EXPANSION280 // Comment.281 int x;]])cpp");282}283 284TEST(SourceCodeTest, getAssociatedRangeClasses) {285 struct RecordDeclsVisitor : AnnotatedCodeVisitor {286 bool VisitRecordDecl(RecordDecl *Decl) override {287 return VisitDeclHelper(Decl);288 }289 };290 RecordDeclsVisitor Visitor;291 292 Visitor.runOverAnnotated("$r[[class A;]]");293 Visitor.runOverAnnotated("$r[[class A {};]]");294 295 // Includes leading template annotation.296 Visitor.runOverAnnotated("$r[[template <typename T> class A;]]");297 Visitor.runOverAnnotated("$r[[template <typename T> class A {};]]");298}299 300TEST(SourceCodeTest, getAssociatedRangeClassTemplateSpecializations) {301 struct CXXRecordDeclsVisitor : AnnotatedCodeVisitor {302 bool VisitCXXRecordDecl(CXXRecordDecl *Decl) override {303 return Decl->getTemplateSpecializationKind() !=304 TSK_ExplicitSpecialization ||305 VisitDeclHelper(Decl);306 }307 };308 CXXRecordDeclsVisitor Visitor;309 310 Visitor.runOverAnnotated(R"cpp(311 template <typename T> class A{};312 $r[[template <> class A<int>;]])cpp");313 Visitor.runOverAnnotated(R"cpp(314 template <typename T> class A{};315 $r[[template <> class A<int> {};]])cpp");316}317 318TEST(SourceCodeTest, getAssociatedRangeFunctions) {319 struct FunctionDeclsVisitor : AnnotatedCodeVisitor {320 bool VisitFunctionDecl(FunctionDecl *Decl) override {321 return VisitDeclHelper(Decl);322 }323 };324 FunctionDeclsVisitor Visitor;325 326 Visitor.runOverAnnotated("$r[[int f();]]");327 Visitor.runOverAnnotated("$r[[int f() { return 0; }]]");328 // Includes leading template annotation.329 Visitor.runOverAnnotated("$r[[template <typename T> int f();]]");330 Visitor.runOverAnnotated("$r[[template <typename T> int f() { return 0; }]]");331}332 333TEST(SourceCodeTest, getAssociatedRangeMemberTemplates) {334 struct CXXMethodDeclsVisitor : AnnotatedCodeVisitor {335 bool VisitCXXMethodDecl(CXXMethodDecl *Decl) override {336 // Only consider the definition of the template.337 return !Decl->doesThisDeclarationHaveABody() || VisitDeclHelper(Decl);338 }339 };340 CXXMethodDeclsVisitor Visitor;341 342 Visitor.runOverAnnotated(R"cpp(343 template <typename C>344 struct A { template <typename T> int member(T v); };345 346 $r[[template <typename C>347 template <typename T>348 int A<C>::member(T v) { return 0; }]])cpp");349}350 351TEST(SourceCodeTest, getAssociatedRangeWithComments) {352 struct VarDeclsVisitor : AnnotatedCodeVisitor {353 bool VisitVarDecl(VarDecl *Decl) override { return VisitDeclHelper(Decl); }354 };355 356 VarDeclsVisitor Visitor;357 auto Visit = [&](llvm::StringRef AnnotatedCode) {358 Visitor.runOverAnnotated(AnnotatedCode, {"-fparse-all-comments"});359 };360 361 // Includes leading comments.362 Visit("$r[[// Comment.\nint x = 4;]]");363 Visit("$r[[// Comment.\nint x = 4;\n]]");364 Visit("$r[[/* Comment.*/\nint x = 4;\n]]");365 // ... even if separated by (extra) horizontal whitespace.366 Visit("$r[[/* Comment.*/ \nint x = 4;\n]]");367 368 // Includes comments even in the presence of trailing whitespace.369 Visit("$r[[// Comment.\nint x = 4;]] ");370 371 // Includes comments when the declaration is followed by the beginning or end372 // of a compound statement.373 Visit(R"cpp(374 void foo() {375 $r[[/* C */376 int x = 4;377 ]]};)cpp");378 Visit(R"cpp(379 void foo() {380 $r[[/* C */381 int x = 4;382 ]]{ class Foo {}; }383 })cpp");384 385 // Includes comments inside macros (when decl is in the same macro).386 Visit(R"cpp(387 #define DECL /* Comment */ int x388 $r[[DECL;]])cpp");389 390 Visit(R"cpp(391 #define DECL int x392 $r[[// Comment393 DECL;]])cpp");394 // Does not include comments when only the comment come from a macro.395 Visit(R"cpp(396 #define COMMENT /* Comment */397 COMMENT398 $r[[int x;]])cpp");399 400 // Includes multi-line comments.401 Visit(R"cpp(402 $r[[/* multi403 * line404 * comment405 */406 int x;]])cpp");407 Visit(R"cpp(408 $r[[// multi409 // line410 // comment411 int x;]])cpp");412 413 // Does not include comments separated by multiple empty lines.414 Visit("// Comment.\n\n\n$r[[int x = 4;\n]]");415 Visit("/* Comment.*/\n\n\n$r[[int x = 4;\n]]");416 417 // Does not include comments before a *series* of declarations.418 Visit(R"cpp(419 // Comment.420 $r[[int x = 4;421 ]]class foo {};)cpp");422 423 // Does not include IfThisThenThat comments424 Visit("// LINT.IfChange.\n$r[[int x = 4;]]");425 Visit("// LINT.ThenChange.\n$r[[int x = 4;]]");426 427 // Includes attributes.428 Visit(R"cpp(429 $r[[__attribute__((deprecated("message")))430 int x;]])cpp");431 432 // Includes attributes and comments together.433 Visit(R"cpp(434 $r[[__attribute__((deprecated("message")))435 // Comment.436 int x;]])cpp");437 438 // Includes attributes through macro expansion.439 Visitor.runOverAnnotated(R"cpp(440 #define MACRO_EXPANSION __attribute__((deprecated("message")))441 $r[[MACRO_EXPANSION442 int x;]])cpp");443 444 // Includes attributes through macro expansion with comments.445 Visitor.runOverAnnotated(R"cpp(446 #define MACRO_EXPANSION __attribute__((deprecated("message")))447 $r[[MACRO_EXPANSION448 // Comment.449 int x;]])cpp");450}451 452TEST(SourceCodeTest, getAssociatedRangeInvalidForPartialExpansions) {453 struct FailingVarDeclsVisitor : TestVisitor {454 FailingVarDeclsVisitor() {}455 bool VisitVarDecl(VarDecl *Decl) override {456 EXPECT_TRUE(getAssociatedRange(*Decl, *Context).isInvalid());457 return true;458 }459 };460 461 FailingVarDeclsVisitor Visitor;462 // Should fail because it only includes a part of the expansion.463 std::string Code = R"cpp(464 #define DECL class foo { }; int x465 DECL;)cpp";466 Visitor.runOver(Code);467}468 469class GetFileRangeForEditTest : public testing::TestWithParam<bool> {};470INSTANTIATE_TEST_SUITE_P(WithAndWithoutExpansions, GetFileRangeForEditTest,471 testing::Bool());472 473TEST_P(GetFileRangeForEditTest, EditRangeWithMacroExpansionsShouldSucceed) {474 // The call expression, whose range we are extracting, includes two macro475 // expansions.476 llvm::Annotations Code(R"cpp(477#define M(a) a * 13478int foo(int x, int y);479int a = $r[[foo(M(1), M(2))]];480)cpp");481 482 CallsVisitor Visitor;483 Visitor.OnCall = [&Code](CallExpr *CE, ASTContext *Context) {484 auto Range = CharSourceRange::getTokenRange(CE->getSourceRange());485 EXPECT_THAT(getFileRangeForEdit(Range, *Context, GetParam()),486 ValueIs(AsRange(Context->getSourceManager(), Code.range("r"))));487 };488 Visitor.runOver(Code.code());489}490 491TEST(SourceCodeTest, EditWholeMacroExpansionShouldSucceed) {492 llvm::Annotations Code(R"cpp(493#define FOO 10494int a = $r[[FOO]];495)cpp");496 497 IntLitVisitor Visitor;498 Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) {499 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());500 EXPECT_THAT(getFileRangeForEdit(Range, *Context),501 ValueIs(AsRange(Context->getSourceManager(), Code.range("r"))));502 };503 Visitor.runOver(Code.code());504}505 506TEST(SourceCodeTest, EditInvolvingExpansionIgnoringExpansionShouldFail) {507 // If we specify to ignore macro expansions, none of these call expressions508 // should have an editable range.509 llvm::Annotations Code(R"cpp(510#define M1(x) x(1)511#define M2(x, y) x ## y512#define M3(x) foobar(x)513#define M4(x, y) x y514#define M5(x) x515int foobar(int);516int a = M1(foobar);517int b = M2(foo, bar(2));518int c = M3(3);519int d = M4(foobar, (4));520int e = M5(foobar) (5);521)cpp");522 523 CallsVisitor Visitor;524 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {525 auto Range = CharSourceRange::getTokenRange(CE->getSourceRange());526 EXPECT_FALSE(527 getFileRangeForEdit(Range, *Context, /*IncludeMacroExpansion=*/false));528 };529 Visitor.runOver(Code.code());530}531 532TEST(SourceCodeTest, InnerNestedTemplate) {533 llvm::Annotations Code(R"cpp(534 template <typename T>535 struct A {};536 template <typename T>537 struct B {};538 template <typename T>539 struct C {};540 541 void f(A<B<C<int>$r[[>>]]);542 )cpp");543 544 TypeLocVisitor Visitor;545 Visitor.OnTypeLoc = [&](TypeLoc TL, ASTContext *Context) {546 if (TL.getSourceRange().isInvalid())547 return;548 549 // There are no macros, so every TypeLoc's range should be valid.550 auto Range = CharSourceRange::getTokenRange(TL.getSourceRange());551 auto LastTokenRange = CharSourceRange::getTokenRange(TL.getEndLoc());552 EXPECT_TRUE(getFileRangeForEdit(Range, *Context,553 /*IncludeMacroExpansion=*/false))554 << TL.getSourceRange().printToString(Context->getSourceManager());555 EXPECT_TRUE(getFileRangeForEdit(LastTokenRange, *Context,556 /*IncludeMacroExpansion=*/false))557 << TL.getEndLoc().printToString(Context->getSourceManager());558 559 if (auto matches = match(560 templateSpecializationTypeLoc(561 loc(templateSpecializationType(562 hasDeclaration(cxxRecordDecl(hasName("A"))))),563 hasTemplateArgumentLoc(564 0, templateArgumentLoc(hasTypeLoc(typeLoc().bind("b"))))),565 TL, *Context);566 !matches.empty()) {567 // A range where the start token is split, but the end token is not.568 auto OuterTL = TL;569 auto MiddleTL = *matches[0].getNodeAs<TypeLoc>("b");570 EXPECT_THAT(571 getFileRangeForEdit(CharSourceRange::getTokenRange(572 MiddleTL.getEndLoc(), OuterTL.getEndLoc()),573 *Context, /*IncludeMacroExpansion=*/false),574 Optional(EqualsAnnotatedRange(Context, Code.range("r"))));575 }576 };577 Visitor.runOver(Code.code(), TypeLocVisitor::Lang_CXX11);578}579 580TEST_P(GetFileRangeForEditTest, EditPartialMacroExpansionShouldFail) {581 std::string Code = R"cpp(582#define BAR 10+583int c = BAR 3.0;584)cpp";585 586 IntLitVisitor Visitor;587 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {588 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());589 EXPECT_FALSE(getFileRangeForEdit(Range, *Context, GetParam()));590 };591 Visitor.runOver(Code);592}593 594TEST_P(GetFileRangeForEditTest, EditWholeMacroArgShouldSucceed) {595 llvm::Annotations Code(R"cpp(596#define FOO(a) a + 7.0;597int a = FOO($r[[10]]);598)cpp");599 600 IntLitVisitor Visitor;601 Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) {602 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());603 EXPECT_THAT(getFileRangeForEdit(Range, *Context, GetParam()),604 ValueIs(AsRange(Context->getSourceManager(), Code.range("r"))));605 };606 Visitor.runOver(Code.code());607}608 609TEST_P(GetFileRangeForEditTest, EditPartialMacroArgShouldSucceed) {610 llvm::Annotations Code(R"cpp(611#define FOO(a) a + 7.0;612int a = FOO($r[[10]] + 10.0);613)cpp");614 615 IntLitVisitor Visitor;616 Visitor.OnIntLit = [&Code](IntegerLiteral *Expr, ASTContext *Context) {617 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());618 EXPECT_THAT(getFileRangeForEdit(Range, *Context, GetParam()),619 ValueIs(AsRange(Context->getSourceManager(), Code.range("r"))));620 };621 Visitor.runOver(Code.code());622}623 624TEST(SourceCodeTest, EditRangeWithMacroExpansionsIsValid) {625 // The call expression, whose range we are extracting, includes two macro626 // expansions.627 llvm::StringRef Code = R"cpp(628#define M(a) a * 13629int foo(int x, int y);630int a = foo(M(1), M(2));631)cpp";632 633 CallsVisitor Visitor;634 Visitor.OnCall = [](CallExpr *CE, ASTContext *Context) {635 auto Range = CharSourceRange::getTokenRange(CE->getSourceRange());636 EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()),637 Succeeded());638 };639 Visitor.runOver(Code);640}641 642TEST(SourceCodeTest, SpellingRangeOfMacroArgIsValid) {643 llvm::StringRef Code = R"cpp(644#define FOO(a) a + 7.0;645int a = FOO(10);646)cpp";647 648 IntLitVisitor Visitor;649 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {650 SourceLocation ArgLoc =651 Context->getSourceManager().getSpellingLoc(Expr->getBeginLoc());652 // The integer literal is a single token.653 auto ArgRange = CharSourceRange::getTokenRange(ArgLoc);654 EXPECT_THAT_ERROR(validateEditRange(ArgRange, Context->getSourceManager()),655 Succeeded());656 };657 Visitor.runOver(Code);658}659 660TEST(SourceCodeTest, InvalidEditRangeIsInvalid) {661 llvm::StringRef Code = "int c = 10;";662 663 // We use the visitor just to get a valid context.664 IntLitVisitor Visitor;665 Visitor.OnIntLit = [](IntegerLiteral *, ASTContext *Context) {666 CharSourceRange Invalid;667 EXPECT_THAT_ERROR(validateEditRange(Invalid, Context->getSourceManager()),668 Failed());669 };670 Visitor.runOver(Code);671}672 673TEST(SourceCodeTest, InvertedEditRangeIsInvalid) {674 llvm::StringRef Code = R"cpp(675int foo(int x);676int a = foo(2);677)cpp";678 679 CallsVisitor Visitor;680 Visitor.OnCall = [](CallExpr *Expr, ASTContext *Context) {681 auto InvertedRange = CharSourceRange::getTokenRange(682 SourceRange(Expr->getEndLoc(), Expr->getBeginLoc()));683 EXPECT_THAT_ERROR(684 validateEditRange(InvertedRange, Context->getSourceManager()),685 Failed());686 };687 Visitor.runOver(Code);688}689 690TEST(SourceCodeTest, MacroArgIsInvalid) {691 llvm::StringRef Code = R"cpp(692#define FOO(a) a + 7.0;693int a = FOO(10);694)cpp";695 696 IntLitVisitor Visitor;697 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {698 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());699 EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()),700 Failed());701 };702 Visitor.runOver(Code);703}704 705TEST(SourceCodeTest, EditWholeMacroExpansionIsInvalid) {706 llvm::StringRef Code = R"cpp(707#define FOO 10708int a = FOO;709)cpp";710 711 IntLitVisitor Visitor;712 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {713 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());714 EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()),715 Failed());716 717 };718 Visitor.runOver(Code);719}720 721TEST(SourceCodeTest, EditPartialMacroExpansionIsInvalid) {722 llvm::StringRef Code = R"cpp(723#define BAR 10+724int c = BAR 3.0;725)cpp";726 727 IntLitVisitor Visitor;728 Visitor.OnIntLit = [](IntegerLiteral *Expr, ASTContext *Context) {729 auto Range = CharSourceRange::getTokenRange(Expr->getSourceRange());730 EXPECT_THAT_ERROR(validateEditRange(Range, Context->getSourceManager()),731 Failed());732 };733 Visitor.runOver(Code);734}735 736TEST(SourceCodeTest, GetCallReturnType_Dependent) {737 llvm::Annotations Code{R"cpp(738template<class T, class F>739void templ(const T& t, F f) {}740 741template<class T, class F>742void templ1(const T& t, F f) {743 $test1[[f(t)]];744}745 746int f_overload(int) { return 1; }747int f_overload(double) { return 2; }748 749void f1() {750 int i = 0;751 templ(i, [](const auto &p) {752 $test2[[f_overload(p)]];753 });754}755 756struct A {757 void f_overload(int);758 void f_overload(double);759};760 761void f2() {762 int i = 0;763 templ(i, [](const auto &p) {764 A a;765 $test3[[a.f_overload(p)]];766 });767}768)cpp"};769 770 llvm::Annotations::Range R1 = Code.range("test1");771 llvm::Annotations::Range R2 = Code.range("test2");772 llvm::Annotations::Range R3 = Code.range("test3");773 774 CallsVisitor Visitor;775 Visitor.OnCall = [&R1, &R2, &R3](CallExpr *Expr, ASTContext *Context) {776 unsigned Begin = Context->getSourceManager().getFileOffset(777 Expr->getSourceRange().getBegin());778 unsigned End = Context->getSourceManager().getFileOffset(779 Expr->getSourceRange().getEnd());780 llvm::Annotations::Range R{Begin, End + 1};781 782 QualType CalleeType = Expr->getCallee()->getType();783 if (R == R1) {784 ASSERT_TRUE(CalleeType->isDependentType());785 EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy);786 } else if (R == R2) {787 ASSERT_FALSE(CalleeType->isDependentType());788 ASSERT_TRUE(CalleeType->isSpecificPlaceholderType(BuiltinType::Overload));789 ASSERT_TRUE(isa<UnresolvedLookupExpr>(Expr->getCallee()));790 EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy);791 } else if (R == R3) {792 ASSERT_FALSE(CalleeType->isDependentType());793 ASSERT_TRUE(794 CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember));795 ASSERT_TRUE(isa<UnresolvedMemberExpr>(Expr->getCallee()));796 EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy);797 }798 };799 Visitor.runOver(Code.code(), CallsVisitor::Lang_CXX14);800}801 802} // end anonymous namespace803