teak-llvm/clang/unittests/AST/StmtPrinterTest.cpp
David Majnemer 65a407c2ce Lex: Use the correct types for MS integer suffixes
Something went wrong with r211426, it is an older version of this code
and should not have been committed.  It was reverted with r211434.

Original commit message:
We didn't properly implement support for the sized integer suffixes.
Suffixes like i16 were essentially ignored instead of mapping them to
the appropriately sized integer type.

This fixes PR20008.

Differential Revision: http://reviews.llvm.org/D4132

llvm-svn: 211441
2014-06-21 18:46:07 +00:00

217 lines
6.6 KiB
C++

//===- unittests/AST/StmtPrinterTest.cpp --- Statement printer tests ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains tests for Stmt::printPretty() and related methods.
//
// Search this file for WRONG to see test cases that are producing something
// completely wrong, invalid C++ or just misleading.
//
// These tests have a coding convention:
// * statements to be printed should be contained within a function named 'A'
// unless it should have some special name (e.g., 'operator+');
// * additional helper declarations are 'Z', 'Y', 'X' and so on.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/SmallString.h"
#include "gtest/gtest.h"
using namespace clang;
using namespace ast_matchers;
using namespace tooling;
namespace {
void PrintStmt(raw_ostream &Out, const ASTContext *Context, const Stmt *S) {
assert(S != nullptr && "Expected non-null Stmt");
PrintingPolicy Policy = Context->getPrintingPolicy();
S->printPretty(Out, /*Helper*/ nullptr, Policy);
}
class PrintMatch : public MatchFinder::MatchCallback {
SmallString<1024> Printed;
unsigned NumFoundStmts;
public:
PrintMatch() : NumFoundStmts(0) {}
virtual void run(const MatchFinder::MatchResult &Result) {
const Stmt *S = Result.Nodes.getStmtAs<Stmt>("id");
if (!S)
return;
NumFoundStmts++;
if (NumFoundStmts > 1)
return;
llvm::raw_svector_ostream Out(Printed);
PrintStmt(Out, Result.Context, S);
}
StringRef getPrinted() const {
return Printed;
}
unsigned getNumFoundStmts() const {
return NumFoundStmts;
}
};
template <typename T>
::testing::AssertionResult
PrintedStmtMatches(StringRef Code, const std::vector<std::string> &Args,
const T &NodeMatch, StringRef ExpectedPrinted) {
PrintMatch Printer;
MatchFinder Finder;
Finder.addMatcher(NodeMatch, &Printer);
std::unique_ptr<FrontendActionFactory> Factory(
newFrontendActionFactory(&Finder));
if (!runToolOnCodeWithArgs(Factory->create(), Code, Args))
return testing::AssertionFailure()
<< "Parsing error in \"" << Code.str() << "\"";
if (Printer.getNumFoundStmts() == 0)
return testing::AssertionFailure()
<< "Matcher didn't find any statements";
if (Printer.getNumFoundStmts() > 1)
return testing::AssertionFailure()
<< "Matcher should match only one statement "
"(found " << Printer.getNumFoundStmts() << ")";
if (Printer.getPrinted() != ExpectedPrinted)
return ::testing::AssertionFailure()
<< "Expected \"" << ExpectedPrinted.str() << "\", "
"got \"" << Printer.getPrinted().str() << "\"";
return ::testing::AssertionSuccess();
}
::testing::AssertionResult
PrintedStmtCXX98Matches(StringRef Code, const StatementMatcher &NodeMatch,
StringRef ExpectedPrinted) {
std::vector<std::string> Args;
Args.push_back("-std=c++98");
Args.push_back("-Wno-unused-value");
return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted);
}
::testing::AssertionResult PrintedStmtCXX98Matches(
StringRef Code,
StringRef ContainingFunction,
StringRef ExpectedPrinted) {
std::vector<std::string> Args;
Args.push_back("-std=c++98");
Args.push_back("-Wno-unused-value");
return PrintedStmtMatches(Code,
Args,
functionDecl(hasName(ContainingFunction),
has(compoundStmt(has(stmt().bind("id"))))),
ExpectedPrinted);
}
::testing::AssertionResult
PrintedStmtCXX11Matches(StringRef Code, const StatementMatcher &NodeMatch,
StringRef ExpectedPrinted) {
std::vector<std::string> Args;
Args.push_back("-std=c++11");
Args.push_back("-Wno-unused-value");
return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted);
}
::testing::AssertionResult PrintedStmtMSMatches(
StringRef Code,
StringRef ContainingFunction,
StringRef ExpectedPrinted) {
std::vector<std::string> Args;
Args.push_back("-target");
Args.push_back("i686-pc-win32");
Args.push_back("-std=c++98");
Args.push_back("-fms-extensions");
Args.push_back("-Wno-unused-value");
return PrintedStmtMatches(Code,
Args,
functionDecl(hasName(ContainingFunction),
has(compoundStmt(has(stmt().bind("id"))))),
ExpectedPrinted);
}
} // unnamed namespace
TEST(StmtPrinter, TestIntegerLiteral) {
ASSERT_TRUE(PrintedStmtCXX98Matches(
"void A() {"
" 1, -1, 1U, 1u,"
" 1L, 1l, -1L, 1UL, 1ul,"
" 1LL, -1LL, 1ULL;"
"}",
"A",
"1 , -1 , 1U , 1U , "
"1L , 1L , -1L , 1UL , 1UL , "
"1LL , -1LL , 1ULL"));
// Should be: with semicolon
}
TEST(StmtPrinter, TestMSIntegerLiteral) {
ASSERT_TRUE(PrintedStmtMSMatches(
"void A() {"
" 1i8, -1i8, 1ui8, "
" 1i16, -1i16, 1ui16, "
" 1i32, -1i32, 1ui32, "
" 1i64, -1i64, 1ui64;"
"}",
"A",
"1i8 , -1i8 , 1Ui8 , "
"1i16 , -1i16 , 1Ui16 , "
"1 , -1 , 1U , "
"1LL , -1LL , 1ULL"));
// Should be: with semicolon
}
TEST(StmtPrinter, TestFloatingPointLiteral) {
ASSERT_TRUE(PrintedStmtCXX98Matches(
"void A() { 1.0f, -1.0f, 1.0, -1.0, 1.0l, -1.0l; }",
"A",
"1.F , -1.F , 1. , -1. , 1.L , -1.L"));
// Should be: with semicolon
}
TEST(StmtPrinter, TestCXXConversionDeclImplicit) {
ASSERT_TRUE(PrintedStmtCXX98Matches(
"struct A {"
"operator void *();"
"A operator&(A);"
"};"
"void bar(void *);"
"void foo(A a, A b) {"
" bar(a & b);"
"}",
memberCallExpr(anything()).bind("id"),
"a & b"));
}
TEST(StmtPrinter, TestCXXConversionDeclExplicit) {
ASSERT_TRUE(PrintedStmtCXX11Matches(
"struct A {"
"operator void *();"
"A operator&(A);"
"};"
"void bar(void *);"
"void foo(A a, A b) {"
" auto x = (a & b).operator void *();"
"}",
memberCallExpr(anything()).bind("id"),
"(a & b)"));
// WRONG; Should be: (a & b).operator void *()
}