diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 884ab56fea47dcf9526645058e1b5bed3e871d4a..8807e3b47b7616cbcfa8572e1a129ed1b1bb7675 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -2072,7 +2072,8 @@ private: void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true, bool CXX11AttributesAllowed = true, - bool AtomicAllowed = true); + bool AtomicAllowed = true, + bool IdentifierRequired = false); void ParseDirectDeclarator(Declarator &D); void ParseParenDeclarator(Declarator &D); void ParseFunctionDeclarator(Declarator &D, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 7185de6fede4ce009f7f823fabddad433a903799..784f69ee68d938a03a03cdb78cfeda95d95aaf49 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -4429,7 +4429,8 @@ bool Parser::isConstructorDeclarator() { void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool VendorAttributesAllowed, bool CXX11AttributesAllowed, - bool AtomicAllowed) { + bool AtomicAllowed, + bool IdentifierRequired) { if (getLangOpts().CPlusPlus11 && CXX11AttributesAllowed && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); @@ -4483,8 +4484,16 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, ParseOpenCLQualifiers(DS); break; - case tok::kw___sptr: case tok::kw___uptr: + // GNU libc headers in C mode use '__uptr' as an identifer which conflicts + // with the MS modifier keyword. + if (VendorAttributesAllowed && !getLangOpts().CPlusPlus && + IdentifierRequired && DS.isEmpty() && NextToken().is(tok::semi) && + PP.getSourceManager().isInSystemHeader(Loc)) { + Tok.setKind(tok::identifier); + continue; + } + case tok::kw___sptr: case tok::kw___w64: case tok::kw___ptr64: case tok::kw___ptr32: @@ -4640,7 +4649,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, DeclSpec DS(AttrFactory); // FIXME: GNU attributes are not allowed here in a new-type-id. - ParseTypeQualifierListOpt(DS); + ParseTypeQualifierListOpt(DS, true, true, true, !D.mayOmitIdentifier()); D.ExtendWithDeclSpec(DS); // Recursively parse the declarator. diff --git a/test/Sema/Inputs/ms-keyword-system-header.h b/test/Sema/Inputs/ms-keyword-system-header.h new file mode 100644 index 0000000000000000000000000000000000000000..13cfe3a6ea326dc9740c1e0fc9fd0f73e8604afd --- /dev/null +++ b/test/Sema/Inputs/ms-keyword-system-header.h @@ -0,0 +1,6 @@ +/* "System header" for testing GNU libc keyword conflict workarounds */ + +typedef union { + union w *__uptr; + int *__iptr; +} WS __attribute__((__transparent_union__)); diff --git a/test/Sema/ms-keyword-system-header.c b/test/Sema/ms-keyword-system-header.c new file mode 100644 index 0000000000000000000000000000000000000000..bf7a9f4c8e4b3fed95ce5ef63a0172e5200b8a4b --- /dev/null +++ b/test/Sema/ms-keyword-system-header.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fms-extensions -D MS -isystem %S/Inputs %s -fsyntax-only -verify +// RUN: %clang_cc1 -isystem %S/Inputs %s -fsyntax-only -verify + +// PR17824: GNU libc uses MS keyword __uptr as an identifier in C mode +#include <ms-keyword-system-header.h> + +void fn() { + WS ws; + ws.__uptr = 0; +#ifdef MS + // expected-error@-2 {{expected identifier}} +#else + // expected-no-diagnostics +#endif +}