brintos

brintos / llvm-project-archived public Read only

0
0
Text · 25.4 KiB · a998954 Raw
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