Home | History | Annotate | Download | only in preprocessor_tests
      1 //
      2 // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 #include "PreprocessorTest.h"
      8 #include "Token.h"
      9 
     10 class LocationTest : public PreprocessorTest
     11 {
     12 protected:
     13     void expectLocation(int count,
     14                         const char* const string[],
     15                         const int length[],
     16                         const pp::SourceLocation& location)
     17     {
     18         ASSERT_TRUE(mPreprocessor.init(count, string, length));
     19 
     20         pp::Token token;
     21         mPreprocessor.lex(&token);
     22         EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
     23         EXPECT_EQ("foo", token.text);
     24 
     25         EXPECT_EQ(location.file, token.location.file);
     26         EXPECT_EQ(location.line, token.location.line);
     27     }
     28 };
     29 
     30 TEST_F(LocationTest, String0_Line1)
     31 {
     32     const char* str = "foo";
     33     pp::SourceLocation loc(0, 1);
     34 
     35     SCOPED_TRACE("String0_Line1");
     36     expectLocation(1, &str, NULL, loc);
     37 }
     38 
     39 TEST_F(LocationTest, String0_Line2)
     40 {
     41     const char* str = "\nfoo";
     42     pp::SourceLocation loc(0, 2);
     43 
     44     SCOPED_TRACE("String0_Line2");
     45     expectLocation(1, &str, NULL, loc);
     46 }
     47 
     48 TEST_F(LocationTest, String1_Line1)
     49 {
     50     const char* const str[] = {"\n\n", "foo"};
     51     pp::SourceLocation loc(1, 1);
     52 
     53     SCOPED_TRACE("String1_Line1");
     54     expectLocation(2, str, NULL, loc);
     55 }
     56 
     57 TEST_F(LocationTest, String1_Line2)
     58 {
     59     const char* const str[] = {"\n\n", "\nfoo"};
     60     pp::SourceLocation loc(1, 2);
     61 
     62     SCOPED_TRACE("String1_Line2");
     63     expectLocation(2, str, NULL, loc);
     64 }
     65 
     66 TEST_F(LocationTest, NewlineInsideCommentCounted)
     67 {
     68     const char* str = "/*\n\n*/foo";
     69     pp::SourceLocation loc(0, 3);
     70 
     71     SCOPED_TRACE("NewlineInsideCommentCounted");
     72     expectLocation(1, &str, NULL, loc);
     73 }
     74 
     75 TEST_F(LocationTest, ErrorLocationAfterComment)
     76 {
     77     const char* str = "/*\n\n*/@";
     78 
     79     ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
     80     EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::INVALID_CHARACTER,
     81                                     pp::SourceLocation(0, 3),
     82                                     "@"));
     83 
     84     pp::Token token;
     85     mPreprocessor.lex(&token);
     86 }
     87 
     88 // The location of a token straddling two or more strings is that of the
     89 // first character of the token.
     90 
     91 TEST_F(LocationTest, TokenStraddlingTwoStrings)
     92 {
     93     const char* const str[] = {"f", "oo"};
     94     pp::SourceLocation loc(0, 1);
     95 
     96     SCOPED_TRACE("TokenStraddlingTwoStrings");
     97     expectLocation(2, str, NULL, loc);
     98 }
     99 
    100 TEST_F(LocationTest, TokenStraddlingThreeStrings)
    101 {
    102     const char* const str[] = {"f", "o", "o"};
    103     pp::SourceLocation loc(0, 1);
    104 
    105     SCOPED_TRACE("TokenStraddlingThreeStrings");
    106     expectLocation(3, str, NULL, loc);
    107 }
    108 
    109 TEST_F(LocationTest, EndOfFileWithoutNewline)
    110 {
    111     const char* const str[] = {"foo"};
    112     ASSERT_TRUE(mPreprocessor.init(1, str, NULL));
    113 
    114     pp::Token token;
    115     mPreprocessor.lex(&token);
    116     EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
    117     EXPECT_EQ("foo", token.text);
    118     EXPECT_EQ(0, token.location.file);
    119     EXPECT_EQ(1, token.location.line);
    120 
    121     mPreprocessor.lex(&token);
    122     EXPECT_EQ(pp::Token::LAST, token.type);
    123     EXPECT_EQ(0, token.location.file);
    124     EXPECT_EQ(1, token.location.line);
    125 }
    126 
    127 TEST_F(LocationTest, EndOfFileAfterNewline)
    128 {
    129     const char* const str[] = {"foo\n"};
    130     ASSERT_TRUE(mPreprocessor.init(1, str, NULL));
    131 
    132     pp::Token token;
    133     mPreprocessor.lex(&token);
    134     EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
    135     EXPECT_EQ("foo", token.text);
    136     EXPECT_EQ(0, token.location.file);
    137     EXPECT_EQ(1, token.location.line);
    138 
    139     mPreprocessor.lex(&token);
    140     EXPECT_EQ(pp::Token::LAST, token.type);
    141     EXPECT_EQ(0, token.location.file);
    142     EXPECT_EQ(2, token.location.line);
    143 }
    144 
    145 TEST_F(LocationTest, EndOfFileAfterEmptyString)
    146 {
    147     const char* const str[] = {"foo\n", "\n", ""};
    148     ASSERT_TRUE(mPreprocessor.init(3, str, NULL));
    149 
    150     pp::Token token;
    151     mPreprocessor.lex(&token);
    152     EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
    153     EXPECT_EQ("foo", token.text);
    154     EXPECT_EQ(0, token.location.file);
    155     EXPECT_EQ(1, token.location.line);
    156 
    157     mPreprocessor.lex(&token);
    158     EXPECT_EQ(pp::Token::LAST, token.type);
    159     EXPECT_EQ(2, token.location.file);
    160     EXPECT_EQ(1, token.location.line);
    161 }
    162 
    163 TEST_F(LocationTest, ValidLineDirective1)
    164 {
    165     const char* str = "#line 10\n"
    166                       "foo";
    167     pp::SourceLocation loc(0, 10);
    168 
    169     SCOPED_TRACE("ValidLineDirective1");
    170     expectLocation(1, &str, NULL, loc);
    171 }
    172 
    173 TEST_F(LocationTest, ValidLineDirective2)
    174 {
    175     const char* str = "#line 10 20\n"
    176                       "foo";
    177     pp::SourceLocation loc(20, 10);
    178 
    179     SCOPED_TRACE("ValidLineDirective2");
    180     expectLocation(1, &str, NULL, loc);
    181 }
    182 
    183 TEST_F(LocationTest, LineDirectiveCommentsIgnored)
    184 {
    185     const char* str = "/* bar */"
    186                       "#"
    187                       "/* bar */"
    188                       "line"
    189                       "/* bar */"
    190                       "10"
    191                       "/* bar */"
    192                       "20"
    193                       "/* bar */"
    194                       "// bar   "
    195                       "\n"
    196                       "foo";
    197     pp::SourceLocation loc(20, 10);
    198 
    199     SCOPED_TRACE("LineDirectiveCommentsIgnored");
    200     expectLocation(1, &str, NULL, loc);
    201 }
    202 
    203 TEST_F(LocationTest, LineDirectiveWithMacro1)
    204 {
    205     const char* str = "#define L 10\n"
    206                       "#define F(x) x\n"
    207                       "#line L F(20)\n"
    208                       "foo";
    209     pp::SourceLocation loc(20, 10);
    210 
    211     SCOPED_TRACE("LineDirectiveWithMacro1");
    212     expectLocation(1, &str, NULL, loc);
    213 }
    214 
    215 TEST_F(LocationTest, LineDirectiveWithMacro2)
    216 {
    217     const char* str = "#define LOC 10 20\n"
    218                       "#line LOC\n"
    219                       "foo";
    220     pp::SourceLocation loc(20, 10);
    221 
    222     SCOPED_TRACE("LineDirectiveWithMacro2");
    223     expectLocation(1, &str, NULL, loc);
    224 }
    225 
    226 TEST_F(LocationTest, LineDirectiveWithPredefinedMacro)
    227 {
    228     const char* str = "#line __LINE__ __FILE__\n"
    229                       "foo";
    230     pp::SourceLocation loc(0, 1);
    231 
    232     SCOPED_TRACE("LineDirectiveWithMacro");
    233     expectLocation(1, &str, NULL, loc);
    234 }
    235 
    236 TEST_F(LocationTest, LineDirectiveNewlineBeforeStringBreak)
    237 {
    238     const char* const str[] = {"#line 10 20\n", "foo"};
    239     // String number is incremented after it is set by the line directive.
    240     // Also notice that line number is reset after the string break.
    241     pp::SourceLocation loc(21, 1);
    242 
    243     SCOPED_TRACE("LineDirectiveNewlineBeforeStringBreak");
    244     expectLocation(2, str, NULL, loc);
    245 }
    246 
    247 TEST_F(LocationTest, LineDirectiveNewlineAfterStringBreak)
    248 {
    249     const char* const str[] = {"#line 10 20", "\nfoo"};
    250     // String number is incremented before it is set by the line directive.
    251     pp::SourceLocation loc(20, 10);
    252 
    253     SCOPED_TRACE("LineDirectiveNewlineAfterStringBreak");
    254     expectLocation(2, str, NULL, loc);
    255 }
    256 
    257 TEST_F(LocationTest, LineDirectiveMissingNewline)
    258 {
    259     const char* str = "#line 10";
    260     ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
    261 
    262     using testing::_;
    263     // Error reported about EOF.
    264     EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::EOF_IN_DIRECTIVE, _, _));
    265 
    266     pp::Token token;
    267     mPreprocessor.lex(&token);
    268 }
    269 
    270 struct LineTestParam
    271 {
    272     const char* str;
    273     pp::Diagnostics::ID id;
    274 };
    275 
    276 class InvalidLineTest : public LocationTest,
    277                         public testing::WithParamInterface<LineTestParam>
    278 {
    279 };
    280 
    281 TEST_P(InvalidLineTest, Identified)
    282 {
    283     LineTestParam param = GetParam();
    284     ASSERT_TRUE(mPreprocessor.init(1, &param.str, NULL));
    285 
    286     using testing::_;
    287     // Invalid line directive call.
    288     EXPECT_CALL(mDiagnostics, print(param.id, pp::SourceLocation(0, 1), _));
    289 
    290     pp::Token token;
    291     mPreprocessor.lex(&token);
    292 }
    293 
    294 static const LineTestParam kParams[] = {
    295     {"#line\n", pp::Diagnostics::INVALID_LINE_DIRECTIVE},
    296     {"#line foo\n", pp::Diagnostics::INVALID_LINE_NUMBER},
    297     {"#line 10 foo\n", pp::Diagnostics::INVALID_FILE_NUMBER},
    298     {"#line 10 20 foo\n", pp::Diagnostics::UNEXPECTED_TOKEN},
    299     {"#line 0xffffffff\n", pp::Diagnostics::INTEGER_OVERFLOW},
    300     {"#line 10 0xffffffff\n", pp::Diagnostics::INTEGER_OVERFLOW}
    301 };
    302 
    303 INSTANTIATE_TEST_CASE_P(All, InvalidLineTest, testing::ValuesIn(kParams));
    304