Skip to content

Commit 5671239

Browse files
committed
parse: process GNU and standard attributes on top-level decls
We would previously reject valid input where GNU attributes preceded the standard attributes on top-level declarations. A previous attribute handling change had begun rejecting this whilst GCC does honour this layout. In practice, this breaks use of `extern "C"` attributed functions which use both standard and GNU attributes as experienced by the Swift runtime. Objective-C deserves an honourable mention for requiring some additional special casing. Because attributes on declarations and definitions differ in semantics, we need to replicate some of the logic for detecting attributes to declarations to which they appertain cannot be attributed. This should match the existing case for the application of GNU attributes to interfaces, protocols, and implementations. Take the opportunity to split out the tooling tests into two cases: ones which process macros and ones which do not. Special thanks to Aaron Ballman for the many hints and extensive rubber ducking that was involved in identifying the various places where we accidentally dropped attributes. Differential Revision: https://reviews.llvm.org/D137979 Fixes: llvm#58229 Reviewed By: aaron.ballman, arphaman (cherry picked from commit b78d538)
1 parent c38d16c commit 5671239

File tree

11 files changed

+145
-71
lines changed

11 files changed

+145
-71
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ Bug Fixes
248248
not satisfied in the event of an instantiation failures in a requires expression's
249249
parameter list. We previously handled this correctly in a constraint evaluation
250250
context, but not in a requires clause evaluated as a boolean.
251+
- GNU attributes being applied prior to standard attributes would be handled
252+
improperly, which was corrected to match the behaviour exhibited by GCC.
253+
`Issue 58229 <https://github.com/llvm/llvm-project/issues/58229>`_
251254

252255
Improvements to Clang's diagnostics
253256
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Parse/Parser.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,15 +1601,16 @@ class Parser : public CodeCompletionHandler {
16011601

16021602
//===--------------------------------------------------------------------===//
16031603
// C99 6.9: External Definitions.
1604-
DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributes &Attrs,
1604+
DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributes &DeclAttrs,
1605+
ParsedAttributes &DeclSpecAttrs,
16051606
ParsingDeclSpec *DS = nullptr);
16061607
bool isDeclarationAfterDeclarator();
16071608
bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
1608-
DeclGroupPtrTy
1609-
ParseDeclarationOrFunctionDefinition(ParsedAttributes &Attrs,
1610-
ParsingDeclSpec *DS = nullptr,
1611-
AccessSpecifier AS = AS_none);
1609+
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
1610+
ParsedAttributes &DeclAttrs, ParsedAttributes &DeclSpecAttrs,
1611+
ParsingDeclSpec *DS = nullptr, AccessSpecifier AS = AS_none);
16121612
DeclGroupPtrTy ParseDeclOrFunctionDefInternal(ParsedAttributes &Attrs,
1613+
ParsedAttributes &DeclSpecAttrs,
16131614
ParsingDeclSpec &DS,
16141615
AccessSpecifier AS);
16151616

@@ -1624,7 +1625,8 @@ class Parser : public CodeCompletionHandler {
16241625

16251626
// Objective-C External Declarations
16261627
void MaybeSkipAttributes(tok::ObjCKeywordKind Kind);
1627-
DeclGroupPtrTy ParseObjCAtDirectives(ParsedAttributes &Attrs);
1628+
DeclGroupPtrTy ParseObjCAtDirectives(ParsedAttributes &DeclAttrs,
1629+
ParsedAttributes &DeclSpecAttrs);
16281630
DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
16291631
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
16301632
ParsedAttributes &prefixAttrs);

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,10 @@ void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs,
254254
if (index == InnerNSs.size()) {
255255
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
256256
Tok.isNot(tok::eof)) {
257-
ParsedAttributes Attrs(AttrFactory);
258-
MaybeParseCXX11Attributes(Attrs);
259-
ParseExternalDeclaration(Attrs);
257+
ParsedAttributes DeclAttrs(AttrFactory);
258+
MaybeParseCXX11Attributes(DeclAttrs);
259+
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
260+
ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs);
260261
}
261262

262263
// The caller is what called check -- we are simply calling
@@ -359,6 +360,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {
359360

360361
ParsedAttributes DeclAttrs(AttrFactory);
361362
MaybeParseCXX11Attributes(DeclAttrs);
363+
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
362364

363365
if (Tok.isNot(tok::l_brace)) {
364366
// Reset the source range in DS, as the leading "extern"
@@ -367,7 +369,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {
367369
DS.SetRangeEnd(SourceLocation());
368370
// ... but anyway remember that such an "extern" was seen.
369371
DS.setExternInLinkageSpec(true);
370-
ParseExternalDeclaration(DeclAttrs, &DS);
372+
ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs, &DS);
371373
return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(
372374
getCurScope(), LinkageSpec, SourceLocation())
373375
: nullptr;
@@ -407,9 +409,9 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {
407409
break;
408410
[[fallthrough]];
409411
default:
410-
ParsedAttributes Attrs(AttrFactory);
411-
MaybeParseCXX11Attributes(Attrs);
412-
ParseExternalDeclaration(Attrs);
412+
ParsedAttributes DeclAttrs(AttrFactory);
413+
MaybeParseCXX11Attributes(DeclAttrs);
414+
ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs);
413415
continue;
414416
}
415417

@@ -439,9 +441,10 @@ Decl *Parser::ParseExportDeclaration() {
439441

440442
if (Tok.isNot(tok::l_brace)) {
441443
// FIXME: Factor out a ParseExternalDeclarationWithAttrs.
442-
ParsedAttributes Attrs(AttrFactory);
443-
MaybeParseCXX11Attributes(Attrs);
444-
ParseExternalDeclaration(Attrs);
444+
ParsedAttributes DeclAttrs(AttrFactory);
445+
MaybeParseCXX11Attributes(DeclAttrs);
446+
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
447+
ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs);
445448
return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl,
446449
SourceLocation());
447450
}
@@ -458,9 +461,10 @@ Decl *Parser::ParseExportDeclaration() {
458461

459462
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
460463
Tok.isNot(tok::eof)) {
461-
ParsedAttributes Attrs(AttrFactory);
462-
MaybeParseCXX11Attributes(Attrs);
463-
ParseExternalDeclaration(Attrs);
464+
ParsedAttributes DeclAttrs(AttrFactory);
465+
MaybeParseCXX11Attributes(DeclAttrs);
466+
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
467+
ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs);
464468
}
465469

466470
T.consumeClose();

clang/lib/Parse/ParseHLSL.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,11 @@ Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd) {
7777

7878
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
7979
// FIXME: support attribute on constants inside cbuffer/tbuffer.
80-
ParsedAttributes Attrs(AttrFactory);
80+
ParsedAttributes DeclAttrs(AttrFactory);
81+
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
8182

82-
DeclGroupPtrTy Result = ParseExternalDeclaration(Attrs);
83+
DeclGroupPtrTy Result =
84+
ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs);
8385
if (!validateDeclsInsideHLSLBuffer(Result, IdentifierLoc, IsCBuffer,
8486
*this)) {
8587
T.skipToEnd();

clang/lib/Parse/ParseObjc.cpp

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) {
4545
/// [OBJC] objc-protocol-definition
4646
/// [OBJC] objc-method-definition
4747
/// [OBJC] '@' 'end'
48-
Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives(ParsedAttributes &Attrs) {
48+
Parser::DeclGroupPtrTy
49+
Parser::ParseObjCAtDirectives(ParsedAttributes &DeclAttrs,
50+
ParsedAttributes &DeclSpecAttrs) {
51+
DeclAttrs.takeAllFrom(DeclSpecAttrs);
52+
4953
SourceLocation AtLoc = ConsumeToken(); // the "@"
5054

5155
if (Tok.is(tok::code_completion)) {
@@ -54,17 +58,29 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives(ParsedAttributes &Attrs) {
5458
return nullptr;
5559
}
5660

61+
switch (Tok.getObjCKeywordID()) {
62+
case tok::objc_interface:
63+
case tok::objc_protocol:
64+
case tok::objc_implementation:
65+
break;
66+
default:
67+
llvm::for_each(DeclAttrs, [this](const auto &Attr) {
68+
if (Attr.isGNUAttribute())
69+
Diag(Tok.getLocation(), diag::err_objc_unexpected_attr);
70+
});
71+
}
72+
5773
Decl *SingleDecl = nullptr;
5874
switch (Tok.getObjCKeywordID()) {
5975
case tok::objc_class:
6076
return ParseObjCAtClassDeclaration(AtLoc);
6177
case tok::objc_interface:
62-
SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, Attrs);
78+
SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DeclAttrs);
6379
break;
6480
case tok::objc_protocol:
65-
return ParseObjCAtProtocolDeclaration(AtLoc, Attrs);
81+
return ParseObjCAtProtocolDeclaration(AtLoc, DeclAttrs);
6682
case tok::objc_implementation:
67-
return ParseObjCAtImplementationDeclaration(AtLoc, Attrs);
83+
return ParseObjCAtImplementationDeclaration(AtLoc, DeclAttrs);
6884
case tok::objc_end:
6985
return ParseObjCAtEndDeclaration(AtLoc);
7086
case tok::objc_compatibility_alias:
@@ -652,21 +668,23 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
652668
if (Tok.is(tok::r_brace))
653669
break;
654670

655-
ParsedAttributes EmptyAttrs(AttrFactory);
671+
ParsedAttributes EmptyDeclAttrs(AttrFactory);
672+
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
656673

657674
// Since we call ParseDeclarationOrFunctionDefinition() instead of
658675
// ParseExternalDeclaration() below (so that this doesn't parse nested
659676
// @interfaces), this needs to duplicate some code from the latter.
660677
if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
661678
SourceLocation DeclEnd;
662679
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
663-
allTUVariables.push_back(ParseDeclaration(
664-
DeclaratorContext::File, DeclEnd, EmptyAttrs, EmptyDeclSpecAttrs));
680+
allTUVariables.push_back(ParseDeclaration(DeclaratorContext::File,
681+
DeclEnd, EmptyDeclAttrs,
682+
EmptyDeclSpecAttrs));
665683
continue;
666684
}
667685

668-
allTUVariables.push_back(
669-
ParseDeclarationOrFunctionDefinition(EmptyAttrs));
686+
allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(
687+
EmptyDeclAttrs, EmptyDeclSpecAttrs));
670688
continue;
671689
}
672690

@@ -2225,9 +2243,11 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc,
22252243
{
22262244
ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl);
22272245
while (!ObjCImplParsing.isFinished() && !isEofOrEom()) {
2228-
ParsedAttributes attrs(AttrFactory);
2229-
MaybeParseCXX11Attributes(attrs);
2230-
if (DeclGroupPtrTy DGP = ParseExternalDeclaration(attrs)) {
2246+
ParsedAttributes DeclAttrs(AttrFactory);
2247+
MaybeParseCXX11Attributes(DeclAttrs);
2248+
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2249+
if (DeclGroupPtrTy DGP =
2250+
ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs)) {
22312251
DeclGroupRef DG = DGP.get();
22322252
DeclsInGroup.append(DG.begin(), DG.end());
22332253
}

clang/lib/Parse/ParseOpenMP.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2245,9 +2245,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
22452245
// Here we expect to see some function declaration.
22462246
if (AS == AS_none) {
22472247
assert(TagType == DeclSpec::TST_unspecified);
2248+
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
22482249
MaybeParseCXX11Attributes(Attrs);
22492250
ParsingDeclSpec PDS(*this);
2250-
Ptr = ParseExternalDeclaration(Attrs, &PDS);
2251+
Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
22512252
} else {
22522253
Ptr =
22532254
ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);

clang/lib/Parse/Parser.cpp

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -739,10 +739,17 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result,
739739
break;
740740
}
741741

742-
ParsedAttributes attrs(AttrFactory);
743-
MaybeParseCXX11Attributes(attrs);
744-
745-
Result = ParseExternalDeclaration(attrs);
742+
ParsedAttributes DeclAttrs(AttrFactory);
743+
ParsedAttributes DeclSpecAttrs(AttrFactory);
744+
// GNU attributes are applied to the declaration specification while the
745+
// standard attributes are applied to the declaration. We parse the two
746+
// attribute sets into different containters so we can apply them during
747+
// the regular parsing process.
748+
while (MaybeParseCXX11Attributes(DeclAttrs) ||
749+
MaybeParseGNUAttributes(DeclSpecAttrs))
750+
;
751+
752+
Result = ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs);
746753
// An empty Result might mean a line with ';' or some parsing error, ignore
747754
// it.
748755
if (Result) {
@@ -785,8 +792,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result,
785792
///
786793
/// [Modules-TS] module-import-declaration
787794
///
788-
Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs,
789-
ParsingDeclSpec *DS) {
795+
Parser::DeclGroupPtrTy
796+
Parser::ParseExternalDeclaration(ParsedAttributes &Attrs,
797+
ParsedAttributes &DeclSpecAttrs,
798+
ParsingDeclSpec *DS) {
790799
DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this);
791800
ParenBraceBracketBalancer BalancerRAIIObj(*this);
792801

@@ -874,7 +883,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs,
874883
// __extension__ silences extension warnings in the subexpression.
875884
ExtensionRAIIObject O(Diags); // Use RAII to do this.
876885
ConsumeToken();
877-
return ParseExternalDeclaration(Attrs);
886+
return ParseExternalDeclaration(Attrs, DeclSpecAttrs);
878887
}
879888
case tok::kw_asm: {
880889
ProhibitAttributes(Attrs);
@@ -902,7 +911,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs,
902911
break;
903912
}
904913
case tok::at:
905-
return ParseObjCAtDirectives(Attrs);
914+
return ParseObjCAtDirectives(Attrs, DeclSpecAttrs);
906915
case tok::minus:
907916
case tok::plus:
908917
if (!getLangOpts().ObjC) {
@@ -950,18 +959,16 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs,
950959
// A function definition cannot start with any of these keywords.
951960
{
952961
SourceLocation DeclEnd;
953-
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
954962
return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs,
955-
EmptyDeclSpecAttrs);
963+
DeclSpecAttrs);
956964
}
957965

958966
case tok::kw_cbuffer:
959967
case tok::kw_tbuffer:
960968
if (getLangOpts().HLSL) {
961969
SourceLocation DeclEnd;
962-
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
963970
return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs,
964-
EmptyDeclSpecAttrs);
971+
DeclSpecAttrs);
965972
}
966973
goto dont_know;
967974

@@ -972,9 +979,8 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs,
972979
Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored)
973980
<< 0;
974981
SourceLocation DeclEnd;
975-
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
976982
return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs,
977-
EmptyDeclSpecAttrs);
983+
DeclSpecAttrs);
978984
}
979985
goto dont_know;
980986

@@ -985,9 +991,8 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs,
985991
// Inline namespaces. Allowed as an extension even in C++03.
986992
if (NextKind == tok::kw_namespace) {
987993
SourceLocation DeclEnd;
988-
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
989994
return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs,
990-
EmptyDeclSpecAttrs);
995+
DeclSpecAttrs);
991996
}
992997

993998
// Parse (then ignore) 'inline' prior to a template instantiation. This is
@@ -996,9 +1001,8 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs,
9961001
Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored)
9971002
<< 1;
9981003
SourceLocation DeclEnd;
999-
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
10001004
return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs,
1001-
EmptyDeclSpecAttrs);
1005+
DeclSpecAttrs);
10021006
}
10031007
}
10041008
goto dont_know;
@@ -1034,7 +1038,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs,
10341038
return nullptr;
10351039
}
10361040
// We can't tell whether this is a function-definition or declaration yet.
1037-
return ParseDeclarationOrFunctionDefinition(Attrs, DS);
1041+
return ParseDeclarationOrFunctionDefinition(Attrs, DeclSpecAttrs, DS);
10381042
}
10391043

10401044
// This routine returns a DeclGroup, if the thing we parsed only contains a
@@ -1099,7 +1103,17 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) {
10991103
/// [OMP] allocate-directive [TODO]
11001104
///
11011105
Parser::DeclGroupPtrTy Parser::ParseDeclOrFunctionDefInternal(
1102-
ParsedAttributes &Attrs, ParsingDeclSpec &DS, AccessSpecifier AS) {
1106+
ParsedAttributes &Attrs, ParsedAttributes &DeclSpecAttrs,
1107+
ParsingDeclSpec &DS, AccessSpecifier AS) {
1108+
// Because we assume that the DeclSpec has not yet been initialised, we simply
1109+
// overwrite the source range and attribute the provided leading declspec
1110+
// attributes.
1111+
assert(DS.getSourceRange().isInvalid() &&
1112+
"expected uninitialised source range");
1113+
DS.SetRangeStart(DeclSpecAttrs.Range.getBegin());
1114+
DS.SetRangeEnd(DeclSpecAttrs.Range.getEnd());
1115+
DS.takeAttributesFrom(DeclSpecAttrs);
1116+
11031117
MaybeParseMicrosoftAttributes(DS.getAttributes());
11041118
// Parse the common declaration-specifiers piece.
11051119
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS,
@@ -1198,17 +1212,18 @@ Parser::DeclGroupPtrTy Parser::ParseDeclOrFunctionDefInternal(
11981212
}
11991213

12001214
Parser::DeclGroupPtrTy Parser::ParseDeclarationOrFunctionDefinition(
1201-
ParsedAttributes &Attrs, ParsingDeclSpec *DS, AccessSpecifier AS) {
1215+
ParsedAttributes &Attrs, ParsedAttributes &DeclSpecAttrs,
1216+
ParsingDeclSpec *DS, AccessSpecifier AS) {
12021217
if (DS) {
1203-
return ParseDeclOrFunctionDefInternal(Attrs, *DS, AS);
1218+
return ParseDeclOrFunctionDefInternal(Attrs, DeclSpecAttrs, *DS, AS);
12041219
} else {
12051220
ParsingDeclSpec PDS(*this);
12061221
// Must temporarily exit the objective-c container scope for
12071222
// parsing c constructs and re-enter objc container scope
12081223
// afterwards.
12091224
ObjCDeclContextSwitch ObjCDC(*this);
12101225

1211-
return ParseDeclOrFunctionDefInternal(Attrs, PDS, AS);
1226+
return ParseDeclOrFunctionDefInternal(Attrs, DeclSpecAttrs, PDS, AS);
12121227
}
12131228
}
12141229

@@ -2350,7 +2365,8 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
23502365
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
23512366
ParsedAttributes Attrs(AttrFactory);
23522367
MaybeParseCXX11Attributes(Attrs);
2353-
DeclGroupPtrTy Result = ParseExternalDeclaration(Attrs);
2368+
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2369+
DeclGroupPtrTy Result = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs);
23542370
if (Result && !getCurScope()->getParent())
23552371
Actions.getASTConsumer().HandleTopLevelDecl(Result.get());
23562372
}

0 commit comments

Comments
 (0)