]> granicus.if.org Git - clang/commitdiff
Diagnose ref-qualifiers occuring after virt-specifier-seq and generate fixit hints
authorEhsan Akhgari <ehsan.akhgari@gmail.com>
Tue, 24 Mar 2015 13:02:50 +0000 (13:02 +0000)
committerEhsan Akhgari <ehsan.akhgari@gmail.com>
Tue, 24 Mar 2015 13:02:50 +0000 (13:02 +0000)
Summary: Follow-up to the fix of PR22075.

Reviewers: rsmith

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D7012

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@233070 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
test/FixIt/fixit-cxx0x.cpp

index ba3fd133cc6dcaf162bd074c5430ca4cadb76943..179bc038d5ede1cfa8039da376726077bbc0390e 100644 (file)
@@ -2214,6 +2214,8 @@ private:
                                BalancedDelimiterTracker &Tracker,
                                bool IsAmbiguous,
                                bool RequiresArg = false);
+  bool ParseRefQualifier(bool &RefQualifierIsLValueRef,
+                         SourceLocation &RefQualifierLoc);
   bool isFunctionDeclaratorIdentifierList();
   void ParseFunctionDeclaratorIdentifierList(
          Declarator &D,
index c19759e596c8ace23d8aa2f63b9e1644de710624..5726fb622c6a0994f12e97d74179c4852329296c 100644 (file)
@@ -5342,15 +5342,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
       }
 
       // 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;
-      }
 
       // C++11 [expr.prim.general]p3:
       //   If a declaration declares a member function or member function
@@ -5446,6 +5439,22 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
                 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
 /// identifier list form for a K&R-style function:  void foo(a,b,c)
 ///
index c92d5f30f954e43db95e1f8e8973b7924cd1f3ed..89da9fbf3c96d4a0caf7560bd98d03f43f219c46 100644 (file)
@@ -2100,13 +2100,13 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
   ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, false);
   D.ExtendWithDeclSpec(DS);
 
+  auto &Function = D.getFunctionTypeInfo();
   if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
     auto DeclSpecCheck = [&] (DeclSpec::TQ TypeQual,
                               const char *FixItName,
                               SourceLocation SpecLoc,
                               unsigned* QualifierLoc) {
       FixItHint Insertion;
-      auto &Function = D.getFunctionTypeInfo();
       if (DS.getTypeQualifiers() & TypeQual) {
         if (!(Function.TypeQuals & TypeQual)) {
           std::string Name(FixItName);
@@ -2122,7 +2122,6 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
           << Insertion;
       }
     };
-    auto &Function = D.getFunctionTypeInfo();
     DeclSpecCheck(DeclSpec::TQ_const, "const", DS.getConstSpecLoc(),
                   &Function.ConstQualifierLoc);
     DeclSpecCheck(DeclSpec::TQ_volatile, "volatile", DS.getVolatileSpecLoc(),
@@ -2130,6 +2129,23 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
     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);
+  }
 }
 
 /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
index 6e096e5e78e6d6dc4c8389308159c204bd78c032..5aebcb3defaa6e2e3b6d7bf92a68542af08509f5 100644 (file)
@@ -159,7 +159,7 @@ namespace MisplacedParameterPack {
   void redundantEllipsisInNonTypeTemplateParameter();
 }
 
-namespace MisplacedDeclSpecAfterVirtSpec {
+namespace MisplacedDeclAndRefSpecAfterVirtSpec {
   struct B {
     virtual void f();
     virtual void f() volatile const;
@@ -168,4 +168,12 @@ namespace MisplacedDeclSpecAfterVirtSpec {
     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'}}
   };
+  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'}}
+  };
 }