Skip to content

Commit a156ebd

Browse files
committed
add parsing lit tests
1 parent 9672490 commit a156ebd

File tree

4 files changed

+102
-42
lines changed

4 files changed

+102
-42
lines changed

clang/include/clang/Parse/Parser.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -859,10 +859,11 @@ class Parser : public CodeCompletionHandler {
859859

860860
/// Helper functions for handling zOS pragmas.
861861
NestedNameSpecifier *zOSParseIdentifier(StringRef PragmaName,
862-
const IdentifierInfo *IdentName);
862+
const IdentifierInfo *IdentName,
863+
SourceLocation &);
863864
bool zOSParseParameterList(StringRef PragmaName,
864865
std::optional<SmallVector<QualType, 4>> &TypeList,
865-
Qualifiers &CVQual);
866+
Qualifiers &CVQual, SourceLocation &);
866867
bool zOSHandlePragmaHelper(tok::TokenKind);
867868

868869
/// Handle the annotation token produced for

clang/lib/Parse/ParsePragma.cpp

Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,42 +1417,53 @@ bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,
14171417
return true;
14181418
}
14191419

1420-
NestedNameSpecifier *
1421-
Parser::zOSParseIdentifier(StringRef PragmaName,
1422-
const IdentifierInfo *IdentName) {
1420+
NestedNameSpecifier *Parser::zOSParseIdentifier(StringRef PragmaName,
1421+
const IdentifierInfo *IdentName,
1422+
SourceLocation &PrevLoc) {
14231423
NestedNameSpecifier *NestedId = nullptr;
1424-
if (Tok.is(tok::coloncolon)) {
1425-
NestedId = NestedNameSpecifier::Create(Actions.Context, IdentName);
1426-
} else if (Actions.CurContext->isNamespace()) {
1427-
auto *NS = cast<NamespaceDecl>(Actions.CurContext);
1428-
NestedId =
1429-
NestedNameSpecifier::Create(Actions.Context, NS->getIdentifier());
1430-
NestedId =
1431-
NestedNameSpecifier::Create(Actions.Context, NestedId, IdentName);
1432-
PP.Lex(Tok);
1424+
if (PP.getLangOpts().CPlusPlus) {
1425+
if (Tok.is(tok::coloncolon)) {
1426+
} else if (Actions.CurContext->isNamespace()) {
1427+
auto *NS = cast<NamespaceDecl>(Actions.CurContext);
1428+
NestedId =
1429+
NestedNameSpecifier::Create(Actions.Context, NS->getIdentifier());
1430+
NestedId =
1431+
NestedNameSpecifier::Create(Actions.Context, NestedId, IdentName);
1432+
PrevLoc = Tok.getLocation();
1433+
PP.Lex(Tok);
1434+
} else {
1435+
NestedId = NestedNameSpecifier::Create(Actions.Context, IdentName);
1436+
PrevLoc = Tok.getLocation();
1437+
PP.Lex(Tok);
1438+
}
1439+
while (Tok.is(tok::coloncolon)) {
1440+
PrevLoc = Tok.getLocation();
1441+
PP.Lex(Tok);
1442+
if (Tok.isNot(tok::identifier)) {
1443+
PP.Diag(Tok.getLocation().isValid() ? Tok.getLocation() : PrevLoc,
1444+
diag::warn_pragma_expected_identifier)
1445+
<< PragmaName;
1446+
return nullptr;
1447+
}
1448+
IdentifierInfo *II = Tok.getIdentifierInfo();
1449+
NestedId = NestedNameSpecifier::Create(Actions.Context, NestedId, II);
1450+
PrevLoc = Tok.getLocation();
1451+
PP.Lex(Tok);
1452+
}
14331453
} else {
14341454
NestedId = NestedNameSpecifier::Create(Actions.Context, IdentName);
1435-
PP.Lex(Tok);
1436-
}
1437-
while (Tok.is(tok::coloncolon)) {
1438-
PP.Lex(Tok);
1439-
IdentifierInfo *II = Tok.getIdentifierInfo();
1440-
if (Tok.isNot(tok::identifier)) {
1441-
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1442-
<< PragmaName;
1443-
return nullptr;
1444-
}
1445-
NestedId = NestedNameSpecifier::Create(Actions.Context, NestedId, II);
1455+
PrevLoc = Tok.getLocation();
14461456
PP.Lex(Tok);
14471457
}
14481458
return NestedId;
14491459
}
14501460

14511461
bool Parser::zOSParseParameterList(
14521462
StringRef PragmaName, std::optional<SmallVector<QualType, 4>> &TypeList,
1453-
Qualifiers &CVQual) {
1463+
Qualifiers &CVQual, SourceLocation &PrevLoc) {
14541464
if (Tok.is(tok::l_paren)) {
14551465
TypeList = SmallVector<QualType, 4>();
1466+
PrevLoc = Tok.getLocation();
14561467
PP.Lex(Tok);
14571468
while (Tok.isNot(tok::eof) && !Tok.is(tok::r_paren)) {
14581469
TypeResult TResult = ParseTypeName(nullptr);
@@ -1462,16 +1473,18 @@ bool Parser::zOSParseParameterList(
14621473
TypeList->push_back(QT);
14631474
}
14641475
}
1465-
if (Tok.is(tok::comma) || Tok.is(tok::identifier))
1476+
if (Tok.is(tok::comma) || Tok.is(tok::identifier)) {
1477+
PrevLoc = Tok.getLocation();
14661478
PP.Lex(Tok);
1479+
}
14671480
}
1468-
if (Tok.is(tok::r_paren))
1481+
if (Tok.is(tok::r_paren)) {
1482+
PrevLoc = Tok.getLocation();
14691483
PP.Lex(Tok);
1470-
else {
1484+
} else {
14711485
// We ate the whole line trying to find the right paren of the parameter
14721486
// list
1473-
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1474-
<< PragmaName;
1487+
PP.Diag(PrevLoc, diag::warn_pragma_expected_identifier) << PragmaName;
14751488
return false;
14761489
}
14771490

@@ -1483,6 +1496,7 @@ bool Parser::zOSParseParameterList(
14831496
assert(Tok.is(tok::kw_volatile));
14841497
CVQual.addVolatile();
14851498
}
1499+
PrevLoc = Tok.getLocation();
14861500
PP.Lex(Tok);
14871501
}
14881502
}
@@ -1504,41 +1518,50 @@ bool Parser::zOSHandlePragmaHelper(tok::TokenKind PragmaKind) {
15041518
ConsumeAnnotationToken(); // The annotation token.
15051519

15061520
do {
1521+
SourceLocation PrevTokLocation = Tok.getLocation();
15071522

15081523
PP.Lex(Tok);
15091524
if (Tok.isNot(tok::l_paren)) {
1510-
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1525+
PP.Diag(Tok.getLocation().isValid() ? Tok.getLocation() : PrevTokLocation,
1526+
diag::warn_pragma_expected_lparen)
15111527
<< PragmaName;
15121528
return false;
15131529
}
15141530

15151531
// C++ could have a nested name, or be qualified with ::.
1532+
PrevTokLocation = Tok.getLocation();
15161533
PP.Lex(Tok);
1517-
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::coloncolon)) {
1518-
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1534+
if (Tok.isNot(tok::identifier) &&
1535+
!(PP.getLangOpts().CPlusPlus && Tok.is(tok::coloncolon))) {
1536+
PP.Diag(Tok.getLocation().isValid() ? Tok.getLocation() : PrevTokLocation,
1537+
diag::warn_pragma_expected_identifier)
15191538
<< PragmaName;
15201539
return false;
15211540
}
15221541

15231542
IdentifierInfo *IdentName = Tok.getIdentifierInfo();
15241543
SourceLocation IdentNameLoc = Tok.getLocation();
1525-
NestedNameSpecifier *NestedId = zOSParseIdentifier(PragmaName, IdentName);
1544+
NestedNameSpecifier *NestedId =
1545+
zOSParseIdentifier(PragmaName, IdentName, PrevTokLocation);
15261546
if (!NestedId)
15271547
return false;
15281548

1529-
if (Tok.isNot(tok::l_paren) && Tok.isNot(tok::r_paren)) {
1530-
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1531-
<< PragmaName;
1532-
return false;
1533-
}
1534-
15351549
// C++ can have a paramater list for overloaded functions.
15361550
// Try to parse the argument types.
15371551
std::optional<SmallVector<QualType, 4>> TypeList;
15381552
Qualifiers CVQual;
15391553

1540-
if (!zOSParseParameterList(PragmaName, TypeList, CVQual))
1554+
if (PP.getLangOpts().CPlusPlus && Tok.is(tok::l_paren)) {
1555+
if (!zOSParseParameterList(PragmaName, TypeList, CVQual, PrevTokLocation))
1556+
return false;
1557+
}
1558+
1559+
if (Tok.isNot(tok::r_paren)) {
1560+
PP.Diag(Tok.getLocation().isValid() ? Tok.getLocation() : PrevTokLocation,
1561+
diag::warn_pragma_expected_rparen)
1562+
<< PragmaName;
15411563
return false;
1564+
}
15421565

15431566
PP.Lex(Tok);
15441567
Actions.ActOnPragmaExport(NestedId, IdentNameLoc, std::move(TypeList),

clang/test/Parser/pragma-export.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %clang_cc1 -triple s390x-ibm-zos -fsyntax-only -verify %s
2+
3+
int x;
4+
5+
#pragma export x // expected-warning {{missing '(' after '#pragma export' - ignoring}}
6+
#pragma export // expected-warning {{missing '(' after '#pragma export' - ignoring}}
7+
#pragma export( // expected-warning {{expected identifier in '#pragma export' - ignored}}
8+
#pragma export(x // expected-warning {{missing ')' after '#pragma export' - ignoring}}
9+
#pragma export(::x) // expected-warning {{expected identifier in '#pragma export' - ignored}}
10+
#pragma export(x)
11+
12+
void f() {
13+
}
14+
15+
#pragma export(f()) // expected-warning {{missing ')' after '#pragma export' - ignoring}}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %clang_cc1 -x c++ -triple s390x-ibm-zos -fsyntax-only -verify %s
2+
3+
int i = 4;
4+
#pragma export(:: // expected-warning {{expected identifier in '#pragma export' - ignored}}
5+
#pragma export(::) // expected-warning {{expected identifier in '#pragma export' - ignored}}
6+
#pragma export(::i)
7+
8+
struct S {
9+
static int i;
10+
};
11+
#pragma export(S:: // expected-warning {{expected identifier in '#pragma export' - ignored}}
12+
#pragma export(S::i // expected-warning {{missing ')' after '#pragma export' - ignoring}}
13+
#pragma export(S::i)
14+
15+
void f(int);
16+
void f(double, double);
17+
#pragma export(f( // expected-warning {{expected identifier in '#pragma export' - ignored}}
18+
#pragma export(f() // expected-warning {{missing ')' after '#pragma export' - ignoring}}
19+
#pragma export(f(int) // expected-warning {{missing ')' after '#pragma export' - ignoring}}
20+
#pragma export(f(double,) // expected-warning {{missing ')' after '#pragma export' - ignoring}}
21+
#pragma export(f(double,double))

0 commit comments

Comments
 (0)