forked from OSchip/llvm-project
Diagnose ref-qualifiers occuring after virt-specifier-seq and generate fixit hints
Summary: Follow-up to the fix of PR22075. Reviewers: rsmith Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D7012 llvm-svn: 233070
This commit is contained in:
parent
9a7adfcf3a
commit
86638e59bf
|
@ -2214,6 +2214,8 @@ private:
|
||||||
BalancedDelimiterTracker &Tracker,
|
BalancedDelimiterTracker &Tracker,
|
||||||
bool IsAmbiguous,
|
bool IsAmbiguous,
|
||||||
bool RequiresArg = false);
|
bool RequiresArg = false);
|
||||||
|
bool ParseRefQualifier(bool &RefQualifierIsLValueRef,
|
||||||
|
SourceLocation &RefQualifierLoc);
|
||||||
bool isFunctionDeclaratorIdentifierList();
|
bool isFunctionDeclaratorIdentifierList();
|
||||||
void ParseFunctionDeclaratorIdentifierList(
|
void ParseFunctionDeclaratorIdentifierList(
|
||||||
Declarator &D,
|
Declarator &D,
|
||||||
|
|
|
@ -5342,15 +5342,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse ref-qualifier[opt].
|
// Parse ref-qualifier[opt].
|
||||||
if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) {
|
if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc))
|
||||||
Diag(Tok, getLangOpts().CPlusPlus11 ?
|
|
||||||
diag::warn_cxx98_compat_ref_qualifier :
|
|
||||||
diag::ext_ref_qualifier);
|
|
||||||
|
|
||||||
RefQualifierIsLValueRef = Tok.is(tok::amp);
|
|
||||||
RefQualifierLoc = ConsumeToken();
|
|
||||||
EndLoc = RefQualifierLoc;
|
EndLoc = RefQualifierLoc;
|
||||||
}
|
|
||||||
|
|
||||||
// C++11 [expr.prim.general]p3:
|
// C++11 [expr.prim.general]p3:
|
||||||
// If a declaration declares a member function or member function
|
// If a declaration declares a member function or member function
|
||||||
|
@ -5446,6 +5439,22 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
|
||||||
FnAttrs, EndLoc);
|
FnAttrs, EndLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ParseRefQualifier - Parses a member function ref-qualifier. Returns
|
||||||
|
/// true if a ref-qualifier is found.
|
||||||
|
bool Parser::ParseRefQualifier(bool &RefQualifierIsLValueRef,
|
||||||
|
SourceLocation &RefQualifierLoc) {
|
||||||
|
if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) {
|
||||||
|
Diag(Tok, getLangOpts().CPlusPlus11 ?
|
||||||
|
diag::warn_cxx98_compat_ref_qualifier :
|
||||||
|
diag::ext_ref_qualifier);
|
||||||
|
|
||||||
|
RefQualifierIsLValueRef = Tok.is(tok::amp);
|
||||||
|
RefQualifierLoc = ConsumeToken();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// isFunctionDeclaratorIdentifierList - This parameter list may have an
|
/// isFunctionDeclaratorIdentifierList - This parameter list may have an
|
||||||
/// identifier list form for a K&R-style function: void foo(a,b,c)
|
/// identifier list form for a K&R-style function: void foo(a,b,c)
|
||||||
///
|
///
|
||||||
|
|
|
@ -2100,13 +2100,13 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
|
||||||
ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, false);
|
ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, false);
|
||||||
D.ExtendWithDeclSpec(DS);
|
D.ExtendWithDeclSpec(DS);
|
||||||
|
|
||||||
|
auto &Function = D.getFunctionTypeInfo();
|
||||||
if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
|
if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
|
||||||
auto DeclSpecCheck = [&] (DeclSpec::TQ TypeQual,
|
auto DeclSpecCheck = [&] (DeclSpec::TQ TypeQual,
|
||||||
const char *FixItName,
|
const char *FixItName,
|
||||||
SourceLocation SpecLoc,
|
SourceLocation SpecLoc,
|
||||||
unsigned* QualifierLoc) {
|
unsigned* QualifierLoc) {
|
||||||
FixItHint Insertion;
|
FixItHint Insertion;
|
||||||
auto &Function = D.getFunctionTypeInfo();
|
|
||||||
if (DS.getTypeQualifiers() & TypeQual) {
|
if (DS.getTypeQualifiers() & TypeQual) {
|
||||||
if (!(Function.TypeQuals & TypeQual)) {
|
if (!(Function.TypeQuals & TypeQual)) {
|
||||||
std::string Name(FixItName);
|
std::string Name(FixItName);
|
||||||
|
@ -2122,7 +2122,6 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
|
||||||
<< Insertion;
|
<< Insertion;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
auto &Function = D.getFunctionTypeInfo();
|
|
||||||
DeclSpecCheck(DeclSpec::TQ_const, "const", DS.getConstSpecLoc(),
|
DeclSpecCheck(DeclSpec::TQ_const, "const", DS.getConstSpecLoc(),
|
||||||
&Function.ConstQualifierLoc);
|
&Function.ConstQualifierLoc);
|
||||||
DeclSpecCheck(DeclSpec::TQ_volatile, "volatile", DS.getVolatileSpecLoc(),
|
DeclSpecCheck(DeclSpec::TQ_volatile, "volatile", DS.getVolatileSpecLoc(),
|
||||||
|
@ -2130,6 +2129,23 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
|
||||||
DeclSpecCheck(DeclSpec::TQ_restrict, "restrict", DS.getRestrictSpecLoc(),
|
DeclSpecCheck(DeclSpec::TQ_restrict, "restrict", DS.getRestrictSpecLoc(),
|
||||||
&Function.RestrictQualifierLoc);
|
&Function.RestrictQualifierLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse ref-qualifiers.
|
||||||
|
bool RefQualifierIsLValueRef = true;
|
||||||
|
SourceLocation RefQualifierLoc;
|
||||||
|
if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) {
|
||||||
|
const char *Name = (RefQualifierIsLValueRef ? "& " : "&& ");
|
||||||
|
FixItHint Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name);
|
||||||
|
Function.RefQualifierIsLValueRef = RefQualifierIsLValueRef;
|
||||||
|
Function.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
|
||||||
|
|
||||||
|
Diag(RefQualifierLoc, diag::err_declspec_after_virtspec)
|
||||||
|
<< (RefQualifierIsLValueRef ? "&" : "&&")
|
||||||
|
<< VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())
|
||||||
|
<< FixItHint::CreateRemoval(RefQualifierLoc)
|
||||||
|
<< Insertion;
|
||||||
|
D.SetRangeEnd(RefQualifierLoc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
|
/// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
|
||||||
|
|
|
@ -159,7 +159,7 @@ namespace MisplacedParameterPack {
|
||||||
void redundantEllipsisInNonTypeTemplateParameter();
|
void redundantEllipsisInNonTypeTemplateParameter();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MisplacedDeclSpecAfterVirtSpec {
|
namespace MisplacedDeclAndRefSpecAfterVirtSpec {
|
||||||
struct B {
|
struct B {
|
||||||
virtual void f();
|
virtual void f();
|
||||||
virtual void f() volatile const;
|
virtual void f() volatile const;
|
||||||
|
@ -168,4 +168,12 @@ namespace MisplacedDeclSpecAfterVirtSpec {
|
||||||
virtual void f() override;
|
virtual void f() override;
|
||||||
virtual void f() override final const volatile; // expected-error {{'const' qualifier may not appear after the virtual specifier 'final'}} expected-error {{'volatile' qualifier may not appear after the virtual specifier 'final'}}
|
virtual void f() override final const volatile; // expected-error {{'const' qualifier may not appear after the virtual specifier 'final'}} expected-error {{'volatile' qualifier may not appear after the virtual specifier 'final'}}
|
||||||
};
|
};
|
||||||
|
struct B2 {
|
||||||
|
virtual void f() &;
|
||||||
|
virtual void f() volatile const &&;
|
||||||
|
};
|
||||||
|
struct D2 : B2 {
|
||||||
|
virtual void f() override &; // expected-error {{'&' qualifier may not appear after the virtual specifier 'override'}}
|
||||||
|
virtual void f() override final const volatile &&; // expected-error {{'const' qualifier may not appear after the virtual specifier 'final'}} expected-error {{'volatile' qualifier may not appear after the virtual specifier 'final'}} expected-error {{'&&' qualifier may not appear after the virtual specifier 'final'}}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue