aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitri Gribenko <gribozavr@gmail.com>2013-02-12 17:27:41 +0000
committerDmitri Gribenko <gribozavr@gmail.com>2013-02-12 17:27:41 +0000
commit1b9e8f7e0bf2c6a2857f1b2208ca5f83b567b835 (patch)
treeea1db9c56b7298bd9e936ab48620947e3f8a493a
parent9ece2bb8499251f3e7cdf65e7a65b38aaeead0d8 (diff)
Accept over-qualified constructor in MSVC emulation mode
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
-rw-r--r--lib/Parse/ParseDecl.cpp9
-rw-r--r--test/CXX/special/class.ctor/p1.cpp6
-rw-r--r--test/SemaCXX/MicrosoftExtensions.cpp4
3 files changed, 12 insertions, 7 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index c5e41445d8..0dd1e0a6f4 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -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);
diff --git a/test/CXX/special/class.ctor/p1.cpp b/test/CXX/special/class.ctor/p1.cpp
index 4d821841e4..23ceebad3b 100644
--- a/test/CXX/special/class.ctor/p1.cpp
+++ b/test/CXX/special/class.ctor/p1.cpp
@@ -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'}}
+};
diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp
index 6b43ea205a..449e24b03b 100644
--- a/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/test/SemaCXX/MicrosoftExtensions.cpp
@@ -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'}}
+};