[PATCH] Diagnose ref-qualifiers occuring after virt-specifier-seq and generate fixit hints
Richard Smith
richard at metafoo.co.uk
Tue Feb 10 17:20:17 PST 2015
On Mon, Jan 26, 2015 at 7:38 AM, Ehsan Akhgari <ehsan.akhgari at gmail.com>
wrote:
> ================
> Comment at: lib/Parse/ParseDeclCXX.cpp:2100-2139
> @@ +2099,42 @@
> + unsigned* QualifierLoc) {
> + FixItHint Insertion;
> + if (DS.getTypeQualifiers() & TypeQual) {
> + if (!(Function.TypeQuals & TypeQual)) {
> + std::string Name(FixItName);
> + Name += " ";
> + Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(),
> Name.c_str());
> + Function.TypeQuals |= TypeQual;
> + *QualifierLoc = SpecLoc.getRawEncoding();
> + }
> + Diag(SpecLoc, diag::err_declspec_after_virtspec)
> + << FixItName
> + << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())
> + << FixItHint::CreateRemoval(SpecLoc)
> + << Insertion;
> + }
> + };
> + DeclSpecCheck(DeclSpec::TQ_const, "const", DS.getConstSpecLoc(),
> + &Function.ConstQualifierLoc);
> + DeclSpecCheck(DeclSpec::TQ_volatile, "volatile",
> DS.getVolatileSpecLoc(),
> + &Function.VolatileQualifierLoc);
> + DeclSpecCheck(DeclSpec::TQ_restrict, "restrict",
> DS.getRestrictSpecLoc(),
> + &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);
> + }
> +}
> ----------------
> rsmith wrote:
> > Maybe only produce a single diagnostic no matter how many specifiers
> were provided? You can then also use `FixItHint::CreateInsertionFromRange`
> to produce a fixit that copies the complete range of specifiers from after
> the virt-specifier to before (this will preserve things like macro names
> and whitespace between the tokens).
> Can you please tell me how that would work? My fixit hints are careful so
> that if you have something like: `void foo() override final &;` you would
> get `void foo() final & override;` whereas if you have `void foo() final
> override final &;` you would get `void foo() final & override;` (IOW you
> won't get two final keywords.)
>
Hmm, yes, this is tricky. It would be great if we remembered fixit hints
across diagnostics; then you could first emit removal fixits for the
redundant qualifiers and later emit an insertion-from-range hint (which
would pick up whatever remains of that range after the redundant qualifiers
are removed). This same issue will affect *any* insertion-from-range fixit
hint, though, so I think you should go ahead with CreateInsertionFromRange
and we can fix the issue with that interacting with other fixits separately.
> I don't know how to do the same with a range based insertion fixit hint...
>
> http://reviews.llvm.org/D7012
>
> EMAIL PREFERENCES
> http://reviews.llvm.org/settings/panel/emailpreferences/
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150210/974307a2/attachment.html>
More information about the cfe-commits
mailing list