aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Parse/ParseDeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParseDeclCXX.cpp')
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp169
1 files changed, 99 insertions, 70 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 081d4d8b1209..ddcbb5615fee 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -155,7 +155,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
// Normal namespace definition, not a nested-namespace-definition.
} else if (InlineLoc.isValid()) {
Diag(InlineLoc, diag::err_inline_nested_namespace_definition);
- } else if (getLangOpts().CPlusPlus2a) {
+ } else if (getLangOpts().CPlusPlus20) {
Diag(ExtraNSs[0].NamespaceLoc,
diag::warn_cxx14_compat_nested_namespace_definition);
if (FirstNestedInlineLoc.isValid())
@@ -290,7 +290,9 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false,
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
+ /*EnteringContext=*/false,
/*MayBePseudoDestructor=*/nullptr,
/*IsTypename=*/false,
/*LastII=*/nullptr,
@@ -530,7 +532,9 @@ Decl *Parser::ParseUsingDirective(DeclaratorContext Context,
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false,
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
+ /*EnteringContext=*/false,
/*MayBePseudoDestructor=*/nullptr,
/*IsTypename=*/false,
/*LastII=*/nullptr,
@@ -597,7 +601,9 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context,
// Parse nested-name-specifier.
IdentifierInfo *LastII = nullptr;
- if (ParseOptionalCXXScopeSpecifier(D.SS, nullptr, /*EnteringContext=*/false,
+ if (ParseOptionalCXXScopeSpecifier(D.SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
+ /*EnteringContext=*/false,
/*MayBePseudoDtor=*/nullptr,
/*IsTypename=*/false,
/*LastII=*/&LastII,
@@ -632,12 +638,12 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context,
D.Name.setConstructorName(Type, IdLoc, IdLoc);
} else {
if (ParseUnqualifiedId(
- D.SS, /*EnteringContext=*/false,
+ D.SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false, /*EnteringContext=*/false,
/*AllowDestructorName=*/true,
- /*AllowConstructorName=*/!(Tok.is(tok::identifier) &&
- NextToken().is(tok::equal)),
- /*AllowDeductionGuide=*/false,
- nullptr, nullptr, D.Name))
+ /*AllowConstructorName=*/
+ !(Tok.is(tok::identifier) && NextToken().is(tok::equal)),
+ /*AllowDeductionGuide=*/false, nullptr, D.Name))
return true;
}
@@ -978,10 +984,10 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
EnterExpressionEvaluationContext Unevaluated(
Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
Sema::ExpressionEvaluationContextRecord::EK_Decltype);
- Result =
- Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) {
- return E->hasPlaceholderType() ? ExprError() : E;
- });
+ Result = Actions.CorrectDelayedTyposInExpr(
+ ParseExpression(), /*InitDecl=*/nullptr,
+ /*RecoverUncorrectedTypos=*/false,
+ [](Expr *E) { return E->hasPlaceholderType() ? ExprError() : E; });
if (Result.isInvalid()) {
DS.SetTypeSpecError();
if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) {
@@ -1115,7 +1121,9 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
// Parse optional nested-name-specifier
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false))
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
+ /*EnteringContext=*/false))
return true;
BaseLoc = Tok.getLocation();
@@ -1139,19 +1147,14 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
// Check whether we have a template-id that names a type.
if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
- if (TemplateId->Kind == TNK_Type_template ||
- TemplateId->Kind == TNK_Dependent_template_name ||
- TemplateId->Kind == TNK_Undeclared_template) {
- AnnotateTemplateIdTokenAsType(/*IsClassName*/true);
+ if (TemplateId->mightBeType()) {
+ AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true);
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
- ParsedType Type = getTypeAnnotation(Tok);
+ TypeResult Type = getTypeAnnotation(Tok);
EndLocation = Tok.getAnnotationEndLoc();
ConsumeAnnotationToken();
-
- if (Type)
- return Type;
- return true;
+ return Type;
}
// Fall through to produce an error below.
@@ -1168,7 +1171,9 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
if (Tok.is(tok::less)) {
// It looks the user intended to write a template-id here, but the
// template-name was wrong. Try to fix that.
- TemplateNameKind TNK = TNK_Type_template;
+ // FIXME: Invoke ParseOptionalCXXScopeSpecifier in a "'template' is neither
+ // required nor permitted" mode, and do this there.
+ TemplateNameKind TNK = TNK_Non_template;
TemplateTy Template;
if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, getCurScope(),
&SS, Template, TNK)) {
@@ -1176,14 +1181,6 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
<< Id;
}
- if (!Template) {
- TemplateArgList TemplateArgs;
- SourceLocation LAngleLoc, RAngleLoc;
- ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs,
- RAngleLoc);
- return true;
- }
-
// Form the template name
UnqualifiedId TemplateName;
TemplateName.setIdentifier(Id, IdLoc);
@@ -1192,8 +1189,9 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),
TemplateName))
return true;
- if (TNK == TNK_Type_template || TNK == TNK_Dependent_template_name)
- AnnotateTemplateIdTokenAsType(/*IsClassName*/true);
+ if (Tok.is(tok::annot_template_id) &&
+ takeTemplateIdAnnotation(Tok)->mightBeType())
+ AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true);
// If we didn't end up with a typename token, there's nothing more we
// can do.
@@ -1203,7 +1201,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
// Retrieve the type from the annotation token, consume that token, and
// return.
EndLocation = Tok.getAnnotationEndLoc();
- ParsedType Type = getTypeAnnotation(Tok);
+ TypeResult Type = getTypeAnnotation(Tok);
ConsumeAnnotationToken();
return Type;
}
@@ -1285,7 +1283,8 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) {
case tok::annot_pragma_ms_pointers_to_members:
return true;
case tok::colon:
- return CouldBeBitfield; // enum E { ... } : 2;
+ return CouldBeBitfield || // enum E { ... } : 2;
+ ColonIsSacred; // _Generic(..., enum E : 2);
// Microsoft compatibility
case tok::kw___cdecl: // struct foo {...} __cdecl x;
case tok::kw___fastcall: // struct foo {...} __fastcall x;
@@ -1547,7 +1546,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
CXXScopeSpec Spec;
bool HasValidSpec = true;
- if (ParseOptionalCXXScopeSpecifier(Spec, nullptr, EnteringContext)) {
+ if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
+ EnteringContext)) {
DS.SetTypeSpecError();
HasValidSpec = false;
}
@@ -1620,9 +1621,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
NameLoc = ConsumeAnnotationToken();
if (TemplateId->Kind == TNK_Undeclared_template) {
- // Try to resolve the template name to a type template.
- Actions.ActOnUndeclaredTypeTemplateName(getCurScope(), TemplateId->Template,
- TemplateId->Kind, NameLoc, Name);
+ // Try to resolve the template name to a type template. May update Kind.
+ Actions.ActOnUndeclaredTypeTemplateName(
+ getCurScope(), TemplateId->Template, TemplateId->Kind, NameLoc, Name);
if (TemplateId->Kind == TNK_Undeclared_template) {
RecoverFromUndeclaredTemplateName(
Name, NameLoc,
@@ -1631,10 +1632,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
}
}
- if (TemplateId && TemplateId->Kind != TNK_Type_template &&
- TemplateId->Kind != TNK_Dependent_template_name) {
+ if (TemplateId && !TemplateId->mightBeType()) {
// The template-name in the simple-template-id refers to
- // something other than a class template. Give an appropriate
+ // something other than a type template. Give an appropriate
// error message and skip to the ';'.
SourceRange Range(NameLoc);
if (SS.isNotEmpty())
@@ -1681,7 +1681,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
Sema::TagUseKind TUK;
- if (DSC == DeclSpecContext::DSC_trailing)
+ if (isDefiningTypeSpecifierContext(DSC) == AllowDefiningTypeSpec::No ||
+ (getLangOpts().OpenMP && OpenMPDirectiveParsing))
TUK = Sema::TUK_Reference;
else if (Tok.is(tok::l_brace) ||
(getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
@@ -1806,7 +1807,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// or explicit instantiation.
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
- if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
+ if (TemplateId->isInvalid()) {
+ // Can't build the declaration.
+ } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
TUK == Sema::TUK_Declaration) {
// This is an explicit instantiation of a class template.
ProhibitAttributes(attrs);
@@ -1826,7 +1829,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) {
ProhibitAttributes(attrs);
TypeResult = Actions.ActOnTagTemplateIdType(TUK, TagType, StartLoc,
- TemplateId->SS,
+ SS,
TemplateId->TemplateKWLoc,
TemplateId->Template,
TemplateId->TemplateNameLoc,
@@ -1876,7 +1879,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Build the class template specialization.
TagOrTempResult = Actions.ActOnClassTemplateSpecialization(
getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(),
- *TemplateId, attrs,
+ SS, *TemplateId, attrs,
MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0]
: nullptr,
TemplateParams ? TemplateParams->size() : 0),
@@ -1962,7 +1965,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
Decl *D =
SkipBody.CheckSameAsPrevious ? SkipBody.New : TagOrTempResult.get();
// Parse the definition body.
- ParseStructUnionBody(StartLoc, TagType, D);
+ ParseStructUnionBody(StartLoc, TagType, cast<RecordDecl>(D));
if (SkipBody.CheckSameAsPrevious &&
!Actions.ActOnDuplicateDefinition(DS, TagOrTempResult.get(),
SkipBody)) {
@@ -2182,7 +2185,6 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
// declarations.
auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
getCurrentClass().LateParsedDeclarations.push_back(LateMethod);
- LateMethod->TemplateScope = getCurScope()->isTemplateParamScope();
// Stash the exception-specification tokens in the late-pased method.
LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens;
@@ -2501,7 +2503,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (isAccessDecl) {
// Collect the scope specifier token we annotated earlier.
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, nullptr,
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
/*EnteringContext=*/false);
if (SS.isInvalid()) {
@@ -2512,8 +2515,9 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Try to parse an unqualified-id.
SourceLocation TemplateKWLoc;
UnqualifiedId Name;
- if (ParseUnqualifiedId(SS, false, true, true, false, nullptr,
- &TemplateKWLoc, Name)) {
+ if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false, false, true, true,
+ false, &TemplateKWLoc, Name)) {
SkipUntil(tok::semi);
return nullptr;
}
@@ -2642,6 +2646,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
}
ParsingDeclarator DeclaratorInfo(*this, DS, DeclaratorContext::MemberContext);
+ if (TemplateInfo.TemplateParams)
+ DeclaratorInfo.setTemplateParameterLists(TemplateParams);
VirtSpecifiers VS;
// Hold late-parsed attributes so we can attach a Decl to them later.
@@ -2656,7 +2662,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
auto &Zero = NextToken();
SmallString<8> Buffer;
- if (Zero.isNot(tok::numeric_constant) || Zero.getLength() != 1 ||
+ if (Zero.isNot(tok::numeric_constant) ||
PP.getSpelling(Zero, Buffer) != "0")
return false;
@@ -2707,6 +2713,11 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
DefinitionKind = FDK_Defaulted;
else if (KW.is(tok::kw_delete))
DefinitionKind = FDK_Deleted;
+ else if (KW.is(tok::code_completion)) {
+ Actions.CodeCompleteAfterFunctionEquals(DeclaratorInfo);
+ cutOffParsing();
+ return nullptr;
+ }
}
}
DeclaratorInfo.setFunctionDefinitionKind(DefinitionKind);
@@ -2714,7 +2725,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
// to a friend declaration, that declaration shall be a definition.
if (DeclaratorInfo.isFunctionDeclarator() &&
- DefinitionKind != FDK_Definition && DS.isFriendSpecified()) {
+ DefinitionKind == FDK_Declaration && DS.isFriendSpecified()) {
// Diagnose attributes that appear before decl specifier:
// [[]] friend int foo();
ProhibitAttributes(FnAttrs);
@@ -2782,7 +2793,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
!DS.isFriendSpecified()) {
// It's a default member initializer.
if (BitfieldSize.get())
- Diag(Tok, getLangOpts().CPlusPlus2a
+ Diag(Tok, getLangOpts().CPlusPlus20
? diag::warn_cxx17_compat_bitfield_member_init
: diag::ext_bitfield_member_init);
HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit;
@@ -2987,7 +2998,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
<< 0 /* default */;
else
Diag(ConsumeToken(), diag::err_default_special_members)
- << getLangOpts().CPlusPlus2a;
+ << getLangOpts().CPlusPlus20;
return ExprError();
}
}
@@ -3334,6 +3345,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
// Each iteration of this loop reads one member-declaration.
ParseCXXClassMemberDeclarationWithPragmas(
CurAS, AccessAttrs, static_cast<DeclSpec::TST>(TagType), TagDecl);
+ MaybeDestroyTemplateIds();
}
T.consumeClose();
} else {
@@ -3359,6 +3371,16 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
// are complete and we can parse the delayed portions of method
// declarations and the lexed inline method definitions, along with any
// delayed attributes.
+
+ // Save the state of Sema.FPFeatures, and change the setting
+ // to the levels specified on the command line. Previous level
+ // will be restored when the RAII object is destroyed.
+ Sema::FPFeaturesStateRAII SaveFPFeaturesState(Actions);
+ FPOptionsOverride NewOverrides;
+ Actions.CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
+ Actions.FpPragmaStack.Act(Tok.getLocation(), Sema::PSK_Reset, StringRef(),
+ 0 /*unused*/);
+
SourceLocation SavedPrevTokLocation = PrevTokLocation;
ParseLexedPragmas(getCurrentClass());
ParseLexedAttributes(getCurrentClass());
@@ -3491,7 +3513,9 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
// parse '::'[opt] nested-name-specifier[opt]
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false))
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
+ /*EnteringContext=*/false))
return true;
// : identifier
@@ -3500,7 +3524,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
// : declype(...)
DeclSpec DS(AttrFactory);
// : template_name<...>
- ParsedType TemplateTypeTy;
+ TypeResult TemplateTypeTy;
if (Tok.is(tok::identifier)) {
// Get the identifier. This may be a member name or a class name,
@@ -3517,15 +3541,11 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
TemplateIdAnnotation *TemplateId = Tok.is(tok::annot_template_id)
? takeTemplateIdAnnotation(Tok)
: nullptr;
- if (TemplateId && (TemplateId->Kind == TNK_Type_template ||
- TemplateId->Kind == TNK_Dependent_template_name ||
- TemplateId->Kind == TNK_Undeclared_template)) {
- AnnotateTemplateIdTokenAsType(/*IsClassName*/true);
+ if (TemplateId && TemplateId->mightBeType()) {
+ AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true);
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
TemplateTypeTy = getTypeAnnotation(Tok);
ConsumeAnnotationToken();
- if (!TemplateTypeTy)
- return true;
} else {
Diag(Tok, diag::err_expected_member_or_base_name);
return true;
@@ -3544,8 +3564,10 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
SourceLocation EllipsisLoc;
TryConsumeToken(tok::ellipsis, EllipsisLoc);
+ if (TemplateTypeTy.isInvalid())
+ return true;
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
- TemplateTypeTy, DS, IdLoc,
+ TemplateTypeTy.get(), DS, IdLoc,
InitList.get(), EllipsisLoc);
} else if(Tok.is(tok::l_paren)) {
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -3555,8 +3577,10 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
ExprVector ArgExprs;
CommaLocsTy CommaLocs;
auto RunSignatureHelp = [&] {
+ if (TemplateTypeTy.isInvalid())
+ return QualType();
QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp(
- getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II,
+ getCurScope(), ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs, II,
T.getOpenLocation());
CalledSignatureHelp = true;
return PreferredType;
@@ -3577,12 +3601,17 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
SourceLocation EllipsisLoc;
TryConsumeToken(tok::ellipsis, EllipsisLoc);
+ if (TemplateTypeTy.isInvalid())
+ return true;
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
- TemplateTypeTy, DS, IdLoc,
+ TemplateTypeTy.get(), DS, IdLoc,
T.getOpenLocation(), ArgExprs,
T.getCloseLocation(), EllipsisLoc);
}
+ if (TemplateTypeTy.isInvalid())
+ return true;
+
if (getLangOpts().CPlusPlus11)
return Diag(Tok, diag::err_expected_either) << tok::l_paren << tok::l_brace;
else
@@ -3908,8 +3937,8 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) {
// after the top-level class is completely defined. Therefore, add
// it to the list of nested classes within its parent.
assert(getCurScope()->isClassScope() && "Nested class outside of class scope?");
- ClassStack.top()->LateParsedDeclarations.push_back(new LateParsedClass(this, Victim));
- Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope();
+ ClassStack.top()->LateParsedDeclarations.push_back(
+ new LateParsedClass(this, Victim));
}
/// Try to parse an 'identifier' which appears within an attribute-token.
@@ -4364,7 +4393,7 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
- // Skip most ms attributes except for a whitelist.
+ // Skip most ms attributes except for a specific list.
while (true) {
SkipUntil(tok::r_square, tok::identifier, StopAtSemi | StopBeforeMatch);
if (Tok.isNot(tok::identifier)) // ']', but also eof