[PATCH] Diagnose ref-qualifiers occuring after virt-specifier-seq and generate fixit hints

Ehsan Akhgari ehsan.akhgari at gmail.com
Mon Jan 26 07:38:17 PST 2015


================
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.)

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/






More information about the cfe-commits mailing list