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

Richard Smith richard at metafoo.co.uk
Fri Jan 16 18:14:37 PST 2015


Looks good, thanks!


================
Comment at: lib/Parse/ParseDecl.cpp:5319-5321
@@ -5318,11 +5318,5 @@
       // Parse ref-qualifier[opt].
-      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();
+      if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) {
         EndLoc = RefQualifierLoc;
       }
 
----------------
Remove braces here, please.

================
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);
+  }
+}
----------------
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).

http://reviews.llvm.org/D7012

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/






More information about the cfe-commits mailing list