]> granicus.if.org Git - clang/commitdiff
Accept over-qualified constructor in MSVC emulation mode
authorDmitri Gribenko <gribozavr@gmail.com>
Tue, 12 Feb 2013 17:27:41 +0000 (17:27 +0000)
committerDmitri Gribenko <gribozavr@gmail.com>
Tue, 12 Feb 2013 17:27:41 +0000 (17:27 +0000)
MSVC accepts this:

class A {
  A::A();
};

Clang accepts regular member functions with extra qualification as an MS
extension, but not constructors.  This changes the parser to defer rejecting
qualified constructors so that the same Sema logic can apply to constructors as
regular member functions.  This also improves the error message when MS
extensions are disabled (in my opinion). Before it was:

/Users/jason/Desktop/test.cpp:2:8: error: expected member name or ';' after declaration specifiers
  A::A();
  ~~~~ ^
1 error generated.

After:

/Users/jason/Desktop/test.cpp:2:6: error: extra qualification on member 'A'
  A::A();
  ~~~^
1 error generated.

Patch by Jason Haslam.

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

lib/Parse/ParseDecl.cpp
test/CXX/special/class.ctor/p1.cpp
test/SemaCXX/MicrosoftExtensions.cpp

index c5e41445d8be057f4069e63e4481b744f4a65a02..0dd1e0a6f4296770dce65877660bbb87058f0d00 100644 (file)
@@ -2274,8 +2274,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
         // name, then the code is ill-formed; this interpretation is
         // reinforced by the NAD status of core issue 635.
         TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next);
-        if ((DSContext == DSC_top_level ||
-             (DSContext == DSC_class && DS.isFriendSpecified())) &&
+        if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
             TemplateId->Name &&
             Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS)) {
           if (isConstructorDeclarator()) {
@@ -2325,8 +2324,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
 
       // If we're in a context where the identifier could be a class name,
       // check whether this is a constructor declaration.
-      if ((DSContext == DSC_top_level ||
-           (DSContext == DSC_class && DS.isFriendSpecified())) &&
+      if ((DSContext == DSC_top_level || DSContext == DSC_class) &&
           Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(),
                                      &SS)) {
         if (isConstructorDeclarator())
@@ -4445,8 +4443,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
       else if (D.getCXXScopeSpec().isSet())
         AllowConstructorName =
           (D.getContext() == Declarator::FileContext ||
-           (D.getContext() == Declarator::MemberContext &&
-            D.getDeclSpec().isFriendSpecified()));
+           D.getContext() == Declarator::MemberContext);
       else
         AllowConstructorName = (D.getContext() == Declarator::MemberContext);
 
index 4d821841e47fdf9b812b14c8a597726007265beb..23ceebad3b3daa4bf4cbb1b77d31352097265539 100644 (file)
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
+
 struct X0 {
   struct type { };
 
@@ -41,3 +41,7 @@ template<typename T> X1<T>::X1() { }
 template<typename T> (X1<T>::X1)(double) { }
 template<typename T> X1<T> X1<T>::f1(int) { return 0; }
 template<typename T> X1<T> (X1<T>::f1)(type) { return 0; }
+
+class A {
+  A::A(); // expected-error{{extra qualification on member 'A'}}
+};
index 6b43ea205af3fc31bf615c712d57f2e4da5393dc..449e24b03b68fbd1c29c21c99d2bc6977a16fe1b 100644 (file)
@@ -204,3 +204,7 @@ struct PR11150 {
 void f() { int __except = 0; }
 
 void ::f(); // expected-warning{{extra qualification on member 'f'}}
+
+class C {
+  C::C(); // expected-warning{{extra qualification on member 'C'}}
+};