mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
2a22a3e1f7
--HG-- rename : gfx/angle/src/compiler/compilerdebug.h => gfx/angle/src/compiler/debug.h
304 lines
8.0 KiB
C++
304 lines
8.0 KiB
C++
//
|
|
// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
//
|
|
|
|
#include "PreprocessorTest.h"
|
|
#include "Token.h"
|
|
|
|
class LocationTest : public PreprocessorTest
|
|
{
|
|
protected:
|
|
void expectLocation(int count,
|
|
const char* const string[],
|
|
const int length[],
|
|
const pp::SourceLocation& location)
|
|
{
|
|
ASSERT_TRUE(mPreprocessor.init(count, string, length));
|
|
|
|
pp::Token token;
|
|
mPreprocessor.lex(&token);
|
|
EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
|
|
EXPECT_EQ("foo", token.text);
|
|
|
|
EXPECT_EQ(location.file, token.location.file);
|
|
EXPECT_EQ(location.line, token.location.line);
|
|
}
|
|
};
|
|
|
|
TEST_F(LocationTest, String0_Line1)
|
|
{
|
|
const char* str = "foo";
|
|
pp::SourceLocation loc(0, 1);
|
|
|
|
SCOPED_TRACE("String0_Line1");
|
|
expectLocation(1, &str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, String0_Line2)
|
|
{
|
|
const char* str = "\nfoo";
|
|
pp::SourceLocation loc(0, 2);
|
|
|
|
SCOPED_TRACE("String0_Line2");
|
|
expectLocation(1, &str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, String1_Line1)
|
|
{
|
|
const char* const str[] = {"\n\n", "foo"};
|
|
pp::SourceLocation loc(1, 1);
|
|
|
|
SCOPED_TRACE("String1_Line1");
|
|
expectLocation(2, str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, String1_Line2)
|
|
{
|
|
const char* const str[] = {"\n\n", "\nfoo"};
|
|
pp::SourceLocation loc(1, 2);
|
|
|
|
SCOPED_TRACE("String1_Line2");
|
|
expectLocation(2, str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, NewlineInsideCommentCounted)
|
|
{
|
|
const char* str = "/*\n\n*/foo";
|
|
pp::SourceLocation loc(0, 3);
|
|
|
|
SCOPED_TRACE("NewlineInsideCommentCounted");
|
|
expectLocation(1, &str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, ErrorLocationAfterComment)
|
|
{
|
|
const char* str = "/*\n\n*/@";
|
|
|
|
ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
|
|
EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::INVALID_CHARACTER,
|
|
pp::SourceLocation(0, 3),
|
|
"@"));
|
|
|
|
pp::Token token;
|
|
mPreprocessor.lex(&token);
|
|
}
|
|
|
|
// The location of a token straddling two or more strings is that of the
|
|
// first character of the token.
|
|
|
|
TEST_F(LocationTest, TokenStraddlingTwoStrings)
|
|
{
|
|
const char* const str[] = {"f", "oo"};
|
|
pp::SourceLocation loc(0, 1);
|
|
|
|
SCOPED_TRACE("TokenStraddlingTwoStrings");
|
|
expectLocation(2, str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, TokenStraddlingThreeStrings)
|
|
{
|
|
const char* const str[] = {"f", "o", "o"};
|
|
pp::SourceLocation loc(0, 1);
|
|
|
|
SCOPED_TRACE("TokenStraddlingThreeStrings");
|
|
expectLocation(3, str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, EndOfFileWithoutNewline)
|
|
{
|
|
const char* const str[] = {"foo"};
|
|
ASSERT_TRUE(mPreprocessor.init(1, str, NULL));
|
|
|
|
pp::Token token;
|
|
mPreprocessor.lex(&token);
|
|
EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
|
|
EXPECT_EQ("foo", token.text);
|
|
EXPECT_EQ(0, token.location.file);
|
|
EXPECT_EQ(1, token.location.line);
|
|
|
|
mPreprocessor.lex(&token);
|
|
EXPECT_EQ(pp::Token::LAST, token.type);
|
|
EXPECT_EQ(0, token.location.file);
|
|
EXPECT_EQ(1, token.location.line);
|
|
}
|
|
|
|
TEST_F(LocationTest, EndOfFileAfterNewline)
|
|
{
|
|
const char* const str[] = {"foo\n"};
|
|
ASSERT_TRUE(mPreprocessor.init(1, str, NULL));
|
|
|
|
pp::Token token;
|
|
mPreprocessor.lex(&token);
|
|
EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
|
|
EXPECT_EQ("foo", token.text);
|
|
EXPECT_EQ(0, token.location.file);
|
|
EXPECT_EQ(1, token.location.line);
|
|
|
|
mPreprocessor.lex(&token);
|
|
EXPECT_EQ(pp::Token::LAST, token.type);
|
|
EXPECT_EQ(0, token.location.file);
|
|
EXPECT_EQ(2, token.location.line);
|
|
}
|
|
|
|
TEST_F(LocationTest, EndOfFileAfterEmptyString)
|
|
{
|
|
const char* const str[] = {"foo\n", "\n", ""};
|
|
ASSERT_TRUE(mPreprocessor.init(3, str, NULL));
|
|
|
|
pp::Token token;
|
|
mPreprocessor.lex(&token);
|
|
EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
|
|
EXPECT_EQ("foo", token.text);
|
|
EXPECT_EQ(0, token.location.file);
|
|
EXPECT_EQ(1, token.location.line);
|
|
|
|
mPreprocessor.lex(&token);
|
|
EXPECT_EQ(pp::Token::LAST, token.type);
|
|
EXPECT_EQ(2, token.location.file);
|
|
EXPECT_EQ(1, token.location.line);
|
|
}
|
|
|
|
TEST_F(LocationTest, ValidLineDirective1)
|
|
{
|
|
const char* str = "#line 10\n"
|
|
"foo";
|
|
pp::SourceLocation loc(0, 10);
|
|
|
|
SCOPED_TRACE("ValidLineDirective1");
|
|
expectLocation(1, &str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, ValidLineDirective2)
|
|
{
|
|
const char* str = "#line 10 20\n"
|
|
"foo";
|
|
pp::SourceLocation loc(20, 10);
|
|
|
|
SCOPED_TRACE("ValidLineDirective2");
|
|
expectLocation(1, &str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, LineDirectiveCommentsIgnored)
|
|
{
|
|
const char* str = "/* bar */"
|
|
"#"
|
|
"/* bar */"
|
|
"line"
|
|
"/* bar */"
|
|
"10"
|
|
"/* bar */"
|
|
"20"
|
|
"/* bar */"
|
|
"// bar "
|
|
"\n"
|
|
"foo";
|
|
pp::SourceLocation loc(20, 10);
|
|
|
|
SCOPED_TRACE("LineDirectiveCommentsIgnored");
|
|
expectLocation(1, &str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, LineDirectiveWithMacro1)
|
|
{
|
|
const char* str = "#define L 10\n"
|
|
"#define F(x) x\n"
|
|
"#line L F(20)\n"
|
|
"foo";
|
|
pp::SourceLocation loc(20, 10);
|
|
|
|
SCOPED_TRACE("LineDirectiveWithMacro1");
|
|
expectLocation(1, &str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, LineDirectiveWithMacro2)
|
|
{
|
|
const char* str = "#define LOC 10 20\n"
|
|
"#line LOC\n"
|
|
"foo";
|
|
pp::SourceLocation loc(20, 10);
|
|
|
|
SCOPED_TRACE("LineDirectiveWithMacro2");
|
|
expectLocation(1, &str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, LineDirectiveWithPredefinedMacro)
|
|
{
|
|
const char* str = "#line __LINE__ __FILE__\n"
|
|
"foo";
|
|
pp::SourceLocation loc(0, 1);
|
|
|
|
SCOPED_TRACE("LineDirectiveWithMacro");
|
|
expectLocation(1, &str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, LineDirectiveNewlineBeforeStringBreak)
|
|
{
|
|
const char* const str[] = {"#line 10 20\n", "foo"};
|
|
// String number is incremented after it is set by the line directive.
|
|
// Also notice that line number is reset after the string break.
|
|
pp::SourceLocation loc(21, 1);
|
|
|
|
SCOPED_TRACE("LineDirectiveNewlineBeforeStringBreak");
|
|
expectLocation(2, str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, LineDirectiveNewlineAfterStringBreak)
|
|
{
|
|
const char* const str[] = {"#line 10 20", "\nfoo"};
|
|
// String number is incremented before it is set by the line directive.
|
|
pp::SourceLocation loc(20, 10);
|
|
|
|
SCOPED_TRACE("LineDirectiveNewlineAfterStringBreak");
|
|
expectLocation(2, str, NULL, loc);
|
|
}
|
|
|
|
TEST_F(LocationTest, LineDirectiveMissingNewline)
|
|
{
|
|
const char* str = "#line 10";
|
|
ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
|
|
|
|
using testing::_;
|
|
// Error reported about EOF.
|
|
EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::EOF_IN_DIRECTIVE, _, _));
|
|
|
|
pp::Token token;
|
|
mPreprocessor.lex(&token);
|
|
}
|
|
|
|
struct LineTestParam
|
|
{
|
|
const char* str;
|
|
pp::Diagnostics::ID id;
|
|
};
|
|
|
|
class InvalidLineTest : public LocationTest,
|
|
public testing::WithParamInterface<LineTestParam>
|
|
{
|
|
};
|
|
|
|
TEST_P(InvalidLineTest, Identified)
|
|
{
|
|
LineTestParam param = GetParam();
|
|
ASSERT_TRUE(mPreprocessor.init(1, ¶m.str, NULL));
|
|
|
|
using testing::_;
|
|
// Invalid line directive call.
|
|
EXPECT_CALL(mDiagnostics, print(param.id, pp::SourceLocation(0, 1), _));
|
|
|
|
pp::Token token;
|
|
mPreprocessor.lex(&token);
|
|
}
|
|
|
|
static const LineTestParam kParams[] = {
|
|
{"#line\n", pp::Diagnostics::INVALID_LINE_DIRECTIVE},
|
|
{"#line foo\n", pp::Diagnostics::INVALID_LINE_NUMBER},
|
|
{"#line 10 foo\n", pp::Diagnostics::INVALID_FILE_NUMBER},
|
|
{"#line 10 20 foo\n", pp::Diagnostics::UNEXPECTED_TOKEN},
|
|
{"#line 0xffffffff\n", pp::Diagnostics::INTEGER_OVERFLOW},
|
|
{"#line 10 0xffffffff\n", pp::Diagnostics::INTEGER_OVERFLOW}
|
|
};
|
|
|
|
INSTANTIATE_TEST_CASE_P(All, InvalidLineTest, testing::ValuesIn(kParams));
|